From e3b557809604d036af6e00c60f012c2025b59a5e Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Sat, 11 Feb 2023 13:38:04 +0100 Subject: Vendor import of llvm-project main llvmorg-16-init-18548-gb0daacf58f41, the last commit before the upstream release/17.x branch was created. --- llvm/lib/Support/APFloat.cpp | 364 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 319 insertions(+), 45 deletions(-) (limited to 'llvm/lib/Support/APFloat.cpp') diff --git a/llvm/lib/Support/APFloat.cpp b/llvm/lib/Support/APFloat.cpp index 2ae28fe066cd..eae4fdb6c3d0 100644 --- a/llvm/lib/Support/APFloat.cpp +++ b/llvm/lib/Support/APFloat.cpp @@ -50,6 +50,23 @@ using namespace llvm; static_assert(APFloatBase::integerPartWidth % 4 == 0, "Part width must be divisible by 4!"); namespace llvm { + + // How the nonfinite values Inf and NaN are represented. + enum class fltNonfiniteBehavior { + // Represents standard IEEE 754 behavior. A value is nonfinite if the + // exponent field is all 1s. In such cases, a value is Inf if the + // significand bits are all zero, and NaN otherwise + IEEE754, + + // Only the Float8E5M2 has this behavior. There is no Inf representation. A + // value is NaN if the exponent field and the mantissa field are all 1s. + // This behavior matches the FP8 E4M3 type described in + // https://arxiv.org/abs/2209.05433. We treat both signed and unsigned NaNs + // as non-signalling, although the paper does not state whether the NaN + // values are signalling or not. + NanOnly, + }; + /* Represents floating point arithmetic semantics. */ struct fltSemantics { /* The largest E such that 2^E is representable; this matches the @@ -67,8 +84,11 @@ namespace llvm { /* Number of bits actually used in the semantics. */ unsigned int sizeInBits; + fltNonfiniteBehavior nonFiniteBehavior = fltNonfiniteBehavior::IEEE754; + // Returns true if any number described by this semantics can be precisely - // represented by the specified semantics. + // represented by the specified semantics. Does not take into account + // the value of fltNonfiniteBehavior. bool isRepresentableBy(const fltSemantics &S) const { return maxExponent <= S.maxExponent && minExponent >= S.minExponent && precision <= S.precision; @@ -80,6 +100,9 @@ namespace llvm { static const fltSemantics semIEEEsingle = {127, -126, 24, 32}; static const fltSemantics semIEEEdouble = {1023, -1022, 53, 64}; static const fltSemantics semIEEEquad = {16383, -16382, 113, 128}; + static const fltSemantics semFloat8E5M2 = {15, -14, 3, 8}; + static const fltSemantics semFloat8E4M3FN = {8, -6, 4, 8, + fltNonfiniteBehavior::NanOnly}; static const fltSemantics semX87DoubleExtended = {16383, -16382, 64, 80}; static const fltSemantics semBogus = {0, 0, 0, 0}; @@ -131,12 +154,16 @@ namespace llvm { return IEEEsingle(); case S_IEEEdouble: return IEEEdouble(); - case S_x87DoubleExtended: - return x87DoubleExtended(); case S_IEEEquad: return IEEEquad(); case S_PPCDoubleDouble: return PPCDoubleDouble(); + case S_Float8E5M2: + return Float8E5M2(); + case S_Float8E4M3FN: + return Float8E4M3FN(); + case S_x87DoubleExtended: + return x87DoubleExtended(); } llvm_unreachable("Unrecognised floating semantics"); } @@ -151,12 +178,16 @@ namespace llvm { return S_IEEEsingle; else if (&Sem == &llvm::APFloat::IEEEdouble()) return S_IEEEdouble; - else if (&Sem == &llvm::APFloat::x87DoubleExtended()) - return S_x87DoubleExtended; else if (&Sem == &llvm::APFloat::IEEEquad()) return S_IEEEquad; else if (&Sem == &llvm::APFloat::PPCDoubleDouble()) return S_PPCDoubleDouble; + else if (&Sem == &llvm::APFloat::Float8E5M2()) + return S_Float8E5M2; + else if (&Sem == &llvm::APFloat::Float8E4M3FN()) + return S_Float8E4M3FN; + else if (&Sem == &llvm::APFloat::x87DoubleExtended()) + return S_x87DoubleExtended; else llvm_unreachable("Unknown floating semantics"); } @@ -173,18 +204,16 @@ namespace llvm { const fltSemantics &APFloatBase::IEEEdouble() { return semIEEEdouble; } - const fltSemantics &APFloatBase::IEEEquad() { - return semIEEEquad; + const fltSemantics &APFloatBase::IEEEquad() { return semIEEEquad; } + const fltSemantics &APFloatBase::PPCDoubleDouble() { + return semPPCDoubleDouble; } + const fltSemantics &APFloatBase::Float8E5M2() { return semFloat8E5M2; } + const fltSemantics &APFloatBase::Float8E4M3FN() { return semFloat8E4M3FN; } const fltSemantics &APFloatBase::x87DoubleExtended() { return semX87DoubleExtended; } - const fltSemantics &APFloatBase::Bogus() { - return semBogus; - } - const fltSemantics &APFloatBase::PPCDoubleDouble() { - return semPPCDoubleDouble; - } + const fltSemantics &APFloatBase::Bogus() { return semBogus; } constexpr RoundingMode APFloatBase::rmNearestTiesToEven; constexpr RoundingMode APFloatBase::rmTowardPositive; @@ -767,6 +796,15 @@ void IEEEFloat::makeNaN(bool SNaN, bool Negative, const APInt *fill) { integerPart *significand = significandParts(); unsigned numParts = partCount(); + APInt fill_storage; + if (semantics->nonFiniteBehavior == fltNonfiniteBehavior::NanOnly) { + // The only NaN representation is where the mantissa is all 1s, which is + // non-signalling. + SNaN = false; + fill_storage = APInt::getAllOnes(semantics->precision - 1); + fill = &fill_storage; + } + // Set the significand bits to the fill. if (!fill || fill->getNumWords() < numParts) APInt::tcSet(significand, 0, numParts); @@ -845,6 +883,11 @@ bool IEEEFloat::isSmallest() const { significandMSB() == 0; } +bool IEEEFloat::isSmallestNormalized() const { + return getCategory() == fcNormal && exponent == semantics->minExponent && + isSignificandAllZerosExceptMSB(); +} + bool IEEEFloat::isSignificandAllOnes() const { // Test if the significand excluding the integral bit is all ones. This allows // us to test for binade boundaries. @@ -867,6 +910,33 @@ bool IEEEFloat::isSignificandAllOnes() const { return true; } +bool IEEEFloat::isSignificandAllOnesExceptLSB() const { + // Test if the significand excluding the integral bit is all ones except for + // the least significant bit. + const integerPart *Parts = significandParts(); + + if (Parts[0] & 1) + return false; + + const unsigned PartCount = partCountForBits(semantics->precision); + for (unsigned i = 0; i < PartCount - 1; i++) { + if (~Parts[i] & ~unsigned{!i}) + return false; + } + + // Set the unused high bits to all ones when we compare. + const unsigned NumHighBits = + PartCount * integerPartWidth - semantics->precision + 1; + assert(NumHighBits <= integerPartWidth && NumHighBits > 0 && + "Can not have more high bits to fill than integerPartWidth"); + const integerPart HighBitFill = ~integerPart(0) + << (integerPartWidth - NumHighBits); + if (~(Parts[PartCount - 1] | HighBitFill | 0x1)) + return false; + + return true; +} + bool IEEEFloat::isSignificandAllZeros() const { // Test if the significand excluding the integral bit is all zeros. This // allows us to test for binade boundaries. @@ -890,11 +960,34 @@ bool IEEEFloat::isSignificandAllZeros() const { return true; } +bool IEEEFloat::isSignificandAllZerosExceptMSB() const { + const integerPart *Parts = significandParts(); + const unsigned PartCount = partCountForBits(semantics->precision); + + for (unsigned i = 0; i < PartCount - 1; i++) { + if (Parts[i]) + return false; + } + + const unsigned NumHighBits = + PartCount * integerPartWidth - semantics->precision + 1; + return Parts[PartCount - 1] == integerPart(1) + << (integerPartWidth - NumHighBits); +} + bool IEEEFloat::isLargest() const { - // The largest number by magnitude in our format will be the floating point - // number with maximum exponent and with significand that is all ones. - return isFiniteNonZero() && exponent == semantics->maxExponent - && isSignificandAllOnes(); + if (semantics->nonFiniteBehavior == fltNonfiniteBehavior::NanOnly) { + // The largest number by magnitude in our format will be the floating point + // number with maximum exponent and with significand that is all ones except + // the LSB. + return isFiniteNonZero() && exponent == semantics->maxExponent && + isSignificandAllOnesExceptLSB(); + } else { + // The largest number by magnitude in our format will be the floating point + // number with maximum exponent and with significand that is all ones. + return isFiniteNonZero() && exponent == semantics->maxExponent && + isSignificandAllOnes(); + } } bool IEEEFloat::isInteger() const { @@ -1313,7 +1406,10 @@ IEEEFloat::opStatus IEEEFloat::handleOverflow(roundingMode rounding_mode) { rounding_mode == rmNearestTiesToAway || (rounding_mode == rmTowardPositive && !sign) || (rounding_mode == rmTowardNegative && sign)) { - category = fcInfinity; + if (semantics->nonFiniteBehavior == fltNonfiniteBehavior::NanOnly) + makeNaN(false, sign); + else + category = fcInfinity; return (opStatus) (opOverflow | opInexact); } @@ -1322,6 +1418,8 @@ IEEEFloat::opStatus IEEEFloat::handleOverflow(roundingMode rounding_mode) { exponent = semantics->maxExponent; tcSetLeastSignificantBits(significandParts(), partCount(), semantics->precision); + if (semantics->nonFiniteBehavior == fltNonfiniteBehavior::NanOnly) + APInt::tcClearBit(significandParts(), 0); return opInexact; } @@ -1421,6 +1519,10 @@ IEEEFloat::opStatus IEEEFloat::normalize(roundingMode rounding_mode, } } + if (semantics->nonFiniteBehavior == fltNonfiniteBehavior::NanOnly && + exponent == semantics->maxExponent && isSignificandAllOnes()) + return handleOverflow(rounding_mode); + /* Now round the number according to rounding_mode given the lost fraction. */ @@ -1457,6 +1559,10 @@ IEEEFloat::opStatus IEEEFloat::normalize(roundingMode rounding_mode, return opInexact; } + + if (semantics->nonFiniteBehavior == fltNonfiniteBehavior::NanOnly && + exponent == semantics->maxExponent && isSignificandAllOnes()) + return handleOverflow(rounding_mode); } /* The normal case - we were and are not denormal, and any @@ -1485,7 +1591,7 @@ IEEEFloat::opStatus IEEEFloat::addOrSubtractSpecials(const IEEEFloat &rhs, case PackCategoriesIntoKey(fcNormal, fcNaN): case PackCategoriesIntoKey(fcInfinity, fcNaN): assign(rhs); - LLVM_FALLTHROUGH; + [[fallthrough]]; case PackCategoriesIntoKey(fcNaN, fcZero): case PackCategoriesIntoKey(fcNaN, fcNormal): case PackCategoriesIntoKey(fcNaN, fcInfinity): @@ -1610,7 +1716,7 @@ IEEEFloat::opStatus IEEEFloat::multiplySpecials(const IEEEFloat &rhs) { case PackCategoriesIntoKey(fcInfinity, fcNaN): assign(rhs); sign = false; - LLVM_FALLTHROUGH; + [[fallthrough]]; case PackCategoriesIntoKey(fcNaN, fcZero): case PackCategoriesIntoKey(fcNaN, fcNormal): case PackCategoriesIntoKey(fcNaN, fcInfinity): @@ -1654,7 +1760,7 @@ IEEEFloat::opStatus IEEEFloat::divideSpecials(const IEEEFloat &rhs) { case PackCategoriesIntoKey(fcInfinity, fcNaN): assign(rhs); sign = false; - LLVM_FALLTHROUGH; + [[fallthrough]]; case PackCategoriesIntoKey(fcNaN, fcZero): case PackCategoriesIntoKey(fcNaN, fcNormal): case PackCategoriesIntoKey(fcNaN, fcInfinity): @@ -1677,7 +1783,10 @@ IEEEFloat::opStatus IEEEFloat::divideSpecials(const IEEEFloat &rhs) { return opOK; case PackCategoriesIntoKey(fcNormal, fcZero): - category = fcInfinity; + if (semantics->nonFiniteBehavior == fltNonfiniteBehavior::NanOnly) + makeNaN(false, sign); + else + category = fcInfinity; return opDivByZero; case PackCategoriesIntoKey(fcInfinity, fcInfinity): @@ -1699,7 +1808,7 @@ IEEEFloat::opStatus IEEEFloat::modSpecials(const IEEEFloat &rhs) { case PackCategoriesIntoKey(fcNormal, fcNaN): case PackCategoriesIntoKey(fcInfinity, fcNaN): assign(rhs); - LLVM_FALLTHROUGH; + [[fallthrough]]; case PackCategoriesIntoKey(fcNaN, fcZero): case PackCategoriesIntoKey(fcNaN, fcNormal): case PackCategoriesIntoKey(fcNaN, fcInfinity): @@ -1737,7 +1846,7 @@ IEEEFloat::opStatus IEEEFloat::remainderSpecials(const IEEEFloat &rhs) { case PackCategoriesIntoKey(fcNormal, fcNaN): case PackCategoriesIntoKey(fcInfinity, fcNaN): assign(rhs); - LLVM_FALLTHROUGH; + [[fallthrough]]; case PackCategoriesIntoKey(fcNaN, fcZero): case PackCategoriesIntoKey(fcNaN, fcNormal): case PackCategoriesIntoKey(fcNaN, fcInfinity): @@ -1963,9 +2072,12 @@ IEEEFloat::opStatus IEEEFloat::mod(const IEEEFloat &rhs) { 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); + int Exp = ilogb(*this) - ilogb(rhs); + IEEEFloat V = scalbn(rhs, Exp, rmNearestTiesToEven); + // V can overflow to NaN with fltNonfiniteBehavior::NanOnly, so explicitly + // check for it. + if (V.isNaN() || compareAbsoluteValue(V) == cmpLessThan) + V = scalbn(rhs, Exp - 1, rmNearestTiesToEven); V.sign = sign; fs = subtract(V, rmNearestTiesToEven); @@ -2192,6 +2304,7 @@ IEEEFloat::opStatus IEEEFloat::convert(const fltSemantics &toSemantics, opStatus fs; int shift; const fltSemantics &fromSemantics = *semantics; + bool is_signaling = isSignaling(); lostFraction = lfExactlyZero; newPartCount = partCountForBits(toSemantics.precision + 1); @@ -2233,7 +2346,9 @@ IEEEFloat::opStatus IEEEFloat::convert(const fltSemantics &toSemantics, } // If this is a truncation, perform the shift before we narrow the storage. - if (shift < 0 && (isFiniteNonZero() || category==fcNaN)) + if (shift < 0 && (isFiniteNonZero() || + (category == fcNaN && semantics->nonFiniteBehavior != + fltNonfiniteBehavior::NanOnly))) lostFraction = shiftRight(significandParts(), oldPartCount, -shift); // Fix the storage so it can hold to new value. @@ -2267,6 +2382,13 @@ IEEEFloat::opStatus IEEEFloat::convert(const fltSemantics &toSemantics, fs = normalize(rounding_mode, lostFraction); *losesInfo = (fs != opOK); } else if (category == fcNaN) { + if (semantics->nonFiniteBehavior == fltNonfiniteBehavior::NanOnly) { + *losesInfo = + fromSemantics.nonFiniteBehavior != fltNonfiniteBehavior::NanOnly; + makeNaN(false, sign); + return is_signaling ? opInvalidOp : opOK; + } + *losesInfo = lostFraction != lfExactlyZero || X86SpecialNan; // For x87 extended precision, we want to make a NaN, not a special NaN if @@ -2277,12 +2399,17 @@ IEEEFloat::opStatus IEEEFloat::convert(const fltSemantics &toSemantics, // Convert of sNaN creates qNaN and raises an exception (invalid op). // This also guarantees that a sNaN does not become Inf on a truncation // that loses all payload bits. - if (isSignaling()) { + if (is_signaling) { makeQuiet(); fs = opInvalidOp; } else { fs = opOK; } + } else if (category == fcInfinity && + semantics->nonFiniteBehavior == fltNonfiniteBehavior::NanOnly) { + makeNaN(false, sign); + *losesInfo = true; + fs = opInexact; } else { *losesInfo = false; fs = opOK; @@ -2523,7 +2650,7 @@ IEEEFloat::convertFromZeroExtendedInteger(const integerPart *parts, unsigned int width, bool isSigned, roundingMode rounding_mode) { unsigned int partCount = partCountForBits(width); - APInt api = APInt(width, makeArrayRef(parts, partCount)); + APInt api = APInt(width, ArrayRef(parts, partCount)); sign = false; if (isSigned && APInt::tcExtractBit(parts, width - 1)) { @@ -3353,6 +3480,60 @@ APInt IEEEFloat::convertHalfAPFloatToAPInt() const { (mysignificand & 0x3ff))); } +APInt IEEEFloat::convertFloat8E5M2APFloatToAPInt() const { + assert(semantics == (const llvm::fltSemantics *)&semFloat8E5M2); + assert(partCount() == 1); + + uint32_t myexponent, mysignificand; + + if (isFiniteNonZero()) { + myexponent = exponent + 15; // bias + mysignificand = (uint32_t)*significandParts(); + if (myexponent == 1 && !(mysignificand & 0x4)) + myexponent = 0; // denormal + } else if (category == fcZero) { + myexponent = 0; + mysignificand = 0; + } else if (category == fcInfinity) { + myexponent = 0x1f; + mysignificand = 0; + } else { + assert(category == fcNaN && "Unknown category!"); + myexponent = 0x1f; + mysignificand = (uint32_t)*significandParts(); + } + + return APInt(8, (((sign & 1) << 7) | ((myexponent & 0x1f) << 2) | + (mysignificand & 0x3))); +} + +APInt IEEEFloat::convertFloat8E4M3FNAPFloatToAPInt() const { + assert(semantics == (const llvm::fltSemantics *)&semFloat8E4M3FN); + assert(partCount() == 1); + + uint32_t myexponent, mysignificand; + + if (isFiniteNonZero()) { + myexponent = exponent + 7; // bias + mysignificand = (uint32_t)*significandParts(); + if (myexponent == 1 && !(mysignificand & 0x8)) + myexponent = 0; // denormal + } else if (category == fcZero) { + myexponent = 0; + mysignificand = 0; + } else if (category == fcInfinity) { + myexponent = 0xf; + mysignificand = 0; + } else { + assert(category == fcNaN && "Unknown category!"); + myexponent = 0xf; + mysignificand = (uint32_t)*significandParts(); + } + + return APInt(8, (((sign & 1) << 7) | ((myexponent & 0xf) << 3) | + (mysignificand & 0x7))); +} + // This function creates an APInt that is just a bit map of the floating // point constant as it would appear in memory. It is not a conversion, // and treating the result as a normal integer is unlikely to be useful. @@ -3376,6 +3557,12 @@ APInt IEEEFloat::bitcastToAPInt() const { if (semantics == (const llvm::fltSemantics *)&semPPCDoubleDoubleLegacy) return convertPPCDoubleDoubleAPFloatToAPInt(); + if (semantics == (const llvm::fltSemantics *)&semFloat8E5M2) + return convertFloat8E5M2APFloatToAPInt(); + + if (semantics == (const llvm::fltSemantics *)&semFloat8E4M3FN) + return convertFloat8E4M3FNAPFloatToAPInt(); + assert(semantics == (const llvm::fltSemantics*)&semX87DoubleExtended && "unknown format!"); return convertF80LongDoubleAPFloatToAPInt(); @@ -3603,10 +3790,61 @@ void IEEEFloat::initFromHalfAPInt(const APInt &api) { } } -/// Treat api as containing the bits of a floating point number. Currently -/// we infer the floating point type from the size of the APInt. The -/// isIEEE argument distinguishes between PPC128 and IEEE128 (not meaningful -/// when the size is anything else). +void IEEEFloat::initFromFloat8E5M2APInt(const APInt &api) { + uint32_t i = (uint32_t)*api.getRawData(); + uint32_t myexponent = (i >> 2) & 0x1f; + uint32_t mysignificand = i & 0x3; + + initialize(&semFloat8E5M2); + assert(partCount() == 1); + + sign = i >> 7; + if (myexponent == 0 && mysignificand == 0) { + makeZero(sign); + } else if (myexponent == 0x1f && mysignificand == 0) { + makeInf(sign); + } else if (myexponent == 0x1f && mysignificand != 0) { + category = fcNaN; + exponent = exponentNaN(); + *significandParts() = mysignificand; + } else { + category = fcNormal; + exponent = myexponent - 15; // bias + *significandParts() = mysignificand; + if (myexponent == 0) // denormal + exponent = -14; + else + *significandParts() |= 0x4; // integer bit + } +} + +void IEEEFloat::initFromFloat8E4M3FNAPInt(const APInt &api) { + uint32_t i = (uint32_t)*api.getRawData(); + uint32_t myexponent = (i >> 3) & 0xf; + uint32_t mysignificand = i & 0x7; + + initialize(&semFloat8E4M3FN); + assert(partCount() == 1); + + sign = i >> 7; + if (myexponent == 0 && mysignificand == 0) { + makeZero(sign); + } else if (myexponent == 0xf && mysignificand == 7) { + category = fcNaN; + exponent = exponentNaN(); + *significandParts() = mysignificand; + } else { + category = fcNormal; + exponent = myexponent - 7; // bias + *significandParts() = mysignificand; + if (myexponent == 0) // denormal + exponent = -6; + else + *significandParts() |= 0x8; // integer bit + } +} + +/// Treat api as containing the bits of a floating point number. void IEEEFloat::initFromAPInt(const fltSemantics *Sem, const APInt &api) { assert(api.getBitWidth() == Sem->sizeInBits); if (Sem == &semIEEEhalf) @@ -3623,6 +3861,10 @@ void IEEEFloat::initFromAPInt(const fltSemantics *Sem, const APInt &api) { return initFromQuadrupleAPInt(api); if (Sem == &semPPCDoubleDoubleLegacy) return initFromPPCDoubleDoubleAPInt(api); + if (Sem == &semFloat8E5M2) + return initFromFloat8E5M2APInt(api); + if (Sem == &semFloat8E4M3FN) + return initFromFloat8E4M3FNAPInt(api); llvm_unreachable(nullptr); } @@ -3650,6 +3892,9 @@ void IEEEFloat::makeLargest(bool Negative) { significand[PartCount - 1] = (NumUnusedHighBits < integerPartWidth) ? (~integerPart(0) >> NumUnusedHighBits) : 0; + + if (semantics->nonFiniteBehavior == fltNonfiniteBehavior::NanOnly) + significand[0] &= ~integerPart(1); } /// Make this number the smallest magnitude denormal number in the given @@ -3675,8 +3920,7 @@ void IEEEFloat::makeSmallestNormalized(bool Negative) { zeroSignificand(); sign = Negative; exponent = semantics->minExponent; - significandParts()[partCountForBits(semantics->precision) - 1] |= - (((integerPart)1) << ((semantics->precision - 1) % integerPartWidth)); + APInt::tcSetBit(significandParts(), semantics->precision - 1); } IEEEFloat::IEEEFloat(const fltSemantics &Sem, const APInt &API) { @@ -3812,9 +4056,9 @@ void IEEEFloat::toString(SmallVectorImpl &Str, unsigned FormatPrecision, // Decompose the number into an APInt and an exponent. int exp = exponent - ((int) semantics->precision - 1); - APInt significand(semantics->precision, - makeArrayRef(significandParts(), - partCountForBits(semantics->precision))); + APInt significand( + semantics->precision, + ArrayRef(significandParts(), partCountForBits(semantics->precision))); // Set FormatPrecision if zero. We want to do this before we // truncate trailing zeros, as those are part of the precision. @@ -3875,6 +4119,11 @@ void IEEEFloat::toString(SmallVectorImpl &Str, unsigned FormatPrecision, // Fill the buffer. unsigned precision = significand.getBitWidth(); + if (precision < 4) { + // We need enough precision to store the value 10. + precision = 4; + significand = significand.zext(precision); + } APInt ten(precision, 10); APInt digit(precision, 0); @@ -4023,6 +4272,8 @@ bool IEEEFloat::getExactInverse(APFloat *inv) const { bool IEEEFloat::isSignaling() const { if (!isNaN()) return false; + if (semantics->nonFiniteBehavior == fltNonfiniteBehavior::NanOnly) + return false; // IEEE-754R 2008 6.2.1: A signaling NaN bit string should be encoded with the // first bit of the trailing significand being 0. @@ -4073,12 +4324,18 @@ IEEEFloat::opStatus IEEEFloat::next(bool nextDown) { break; } - // nextUp(getLargest()) == INFINITY if (isLargest() && !isNegative()) { - APInt::tcSet(significandParts(), 0, partCount()); - category = fcInfinity; - exponent = semantics->maxExponent + 1; - break; + if (semantics->nonFiniteBehavior == fltNonfiniteBehavior::NanOnly) { + // nextUp(getLargest()) == NAN + makeNaN(); + break; + } else { + // nextUp(getLargest()) == INFINITY + APInt::tcSet(significandParts(), 0, partCount()); + category = fcInfinity; + exponent = semantics->maxExponent + 1; + break; + } } // nextUp(normal) == normal + inc. @@ -4150,6 +4407,8 @@ IEEEFloat::opStatus IEEEFloat::next(bool nextDown) { } APFloatBase::ExponentType IEEEFloat::exponentNaN() const { + if (semantics->nonFiniteBehavior == fltNonfiniteBehavior::NanOnly) + return semantics->maxExponent; return semantics->maxExponent + 1; } @@ -4162,6 +4421,11 @@ APFloatBase::ExponentType IEEEFloat::exponentZero() const { } void IEEEFloat::makeInf(bool Negative) { + if (semantics->nonFiniteBehavior == fltNonfiniteBehavior::NanOnly) { + // There is no Inf, so make NaN instead. + makeNaN(false, Negative); + return; + } category = fcInfinity; sign = Negative; exponent = exponentInf(); @@ -4177,7 +4441,8 @@ void IEEEFloat::makeZero(bool Negative) { void IEEEFloat::makeQuiet() { assert(isNaN()); - APInt::tcSetBit(significandParts(), semantics->precision - 2); + if (semantics->nonFiniteBehavior != fltNonfiniteBehavior::NanOnly) + APInt::tcSetBit(significandParts(), semantics->precision - 2); } int ilogb(const IEEEFloat &Arg) { @@ -4753,6 +5018,15 @@ bool DoubleAPFloat::isSmallest() const { return Tmp.compare(*this) == cmpEqual; } +bool DoubleAPFloat::isSmallestNormalized() const { + if (getCategory() != fcNormal) + return false; + + DoubleAPFloat Tmp(*this); + Tmp.makeSmallestNormalized(this->isNegative()); + return Tmp.compare(*this) == cmpEqual; +} + bool DoubleAPFloat::isLargest() const { if (getCategory() != fcNormal) return false; -- cgit v1.2.3