aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Support/APFloat.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2023-02-11 12:38:04 +0000
committerDimitry Andric <dim@FreeBSD.org>2023-02-11 12:38:11 +0000
commite3b557809604d036af6e00c60f012c2025b59a5e (patch)
tree8a11ba2269a3b669601e2fd41145b174008f4da8 /llvm/lib/Support/APFloat.cpp
parent08e8dd7b9db7bb4a9de26d44c1cbfd24e869c014 (diff)
downloadsrc-e3b557809604d036af6e00c60f012c2025b59a5e.tar.gz
src-e3b557809604d036af6e00c60f012c2025b59a5e.zip
Vendor import of llvm-project main llvmorg-16-init-18548-gb0daacf58f41,vendor/llvm-project/llvmorg-16-init-18548-gb0daacf58f41
the last commit before the upstream release/17.x branch was created.
Diffstat (limited to 'llvm/lib/Support/APFloat.cpp')
-rw-r--r--llvm/lib/Support/APFloat.cpp364
1 files changed, 319 insertions, 45 deletions
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<char> &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<char> &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;