aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Support/APFloat.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Support/APFloat.cpp')
-rw-r--r--llvm/lib/Support/APFloat.cpp87
1 files changed, 74 insertions, 13 deletions
diff --git a/llvm/lib/Support/APFloat.cpp b/llvm/lib/Support/APFloat.cpp
index 283fcc1..1209bf7 100644
--- a/llvm/lib/Support/APFloat.cpp
+++ b/llvm/lib/Support/APFloat.cpp
@@ -68,6 +68,10 @@ enum class fltNonfiniteBehavior {
// `fltNanEncoding` enum. We treat all NaNs as quiet, as the available
// encodings do not distinguish between signalling and quiet NaN.
NanOnly,
+
+ // This behavior is present in Float6E3M2FN and Float6E2M3FN types,
+ // which do not support Inf or NaN values.
+ FiniteOnly,
};
// How NaN values are represented. This is curently only used in combination
@@ -139,6 +143,10 @@ static constexpr fltSemantics semFloat8E4M3FNUZ = {
static constexpr fltSemantics semFloat8E4M3B11FNUZ = {
4, -10, 4, 8, fltNonfiniteBehavior::NanOnly, fltNanEncoding::NegativeZero};
static constexpr fltSemantics semFloatTF32 = {127, -126, 11, 19};
+static constexpr fltSemantics semFloat6E3M2FN = {
+ 4, -2, 3, 6, fltNonfiniteBehavior::FiniteOnly};
+static constexpr fltSemantics semFloat6E2M3FN = {
+ 2, 0, 4, 6, fltNonfiniteBehavior::FiniteOnly};
static constexpr fltSemantics semX87DoubleExtended = {16383, -16382, 64, 80};
static constexpr fltSemantics semBogus = {0, 0, 0, 0};
@@ -206,6 +214,10 @@ const llvm::fltSemantics &APFloatBase::EnumToSemantics(Semantics S) {
return Float8E4M3B11FNUZ();
case S_FloatTF32:
return FloatTF32();
+ case S_Float6E3M2FN:
+ return Float6E3M2FN();
+ case S_Float6E2M3FN:
+ return Float6E2M3FN();
case S_x87DoubleExtended:
return x87DoubleExtended();
}
@@ -238,6 +250,10 @@ APFloatBase::SemanticsToEnum(const llvm::fltSemantics &Sem) {
return S_Float8E4M3B11FNUZ;
else if (&Sem == &llvm::APFloat::FloatTF32())
return S_FloatTF32;
+ else if (&Sem == &llvm::APFloat::Float6E3M2FN())
+ return S_Float6E3M2FN;
+ else if (&Sem == &llvm::APFloat::Float6E2M3FN())
+ return S_Float6E2M3FN;
else if (&Sem == &llvm::APFloat::x87DoubleExtended())
return S_x87DoubleExtended;
else
@@ -260,6 +276,8 @@ const fltSemantics &APFloatBase::Float8E4M3B11FNUZ() {
return semFloat8E4M3B11FNUZ;
}
const fltSemantics &APFloatBase::FloatTF32() { return semFloatTF32; }
+const fltSemantics &APFloatBase::Float6E3M2FN() { return semFloat6E3M2FN; }
+const fltSemantics &APFloatBase::Float6E2M3FN() { return semFloat6E2M3FN; }
const fltSemantics &APFloatBase::x87DoubleExtended() {
return semX87DoubleExtended;
}
@@ -878,6 +896,9 @@ void IEEEFloat::copySignificand(const IEEEFloat &rhs) {
for the significand. If double or longer, this is a signalling NaN,
which may not be ideal. If float, this is QNaN(0). */
void IEEEFloat::makeNaN(bool SNaN, bool Negative, const APInt *fill) {
+ if (semantics->nonFiniteBehavior == fltNonfiniteBehavior::FiniteOnly)
+ llvm_unreachable("This floating point format does not support NaN");
+
category = fcNaN;
sign = Negative;
exponent = exponentNaN();
@@ -1499,16 +1520,18 @@ static void tcSetLeastSignificantBits(APInt::WordType *dst, unsigned parts,
/* Handle overflow. Sign is preserved. We either become infinity or
the largest finite number. */
IEEEFloat::opStatus IEEEFloat::handleOverflow(roundingMode rounding_mode) {
- /* Infinity? */
- if (rounding_mode == rmNearestTiesToEven ||
- rounding_mode == rmNearestTiesToAway ||
- (rounding_mode == rmTowardPositive && !sign) ||
- (rounding_mode == rmTowardNegative && sign)) {
- if (semantics->nonFiniteBehavior == fltNonfiniteBehavior::NanOnly)
- makeNaN(false, sign);
- else
- category = fcInfinity;
- return (opStatus) (opOverflow | opInexact);
+ if (semantics->nonFiniteBehavior != fltNonfiniteBehavior::FiniteOnly) {
+ /* Infinity? */
+ if (rounding_mode == rmNearestTiesToEven ||
+ rounding_mode == rmNearestTiesToAway ||
+ (rounding_mode == rmTowardPositive && !sign) ||
+ (rounding_mode == rmTowardNegative && sign)) {
+ if (semantics->nonFiniteBehavior == fltNonfiniteBehavior::NanOnly)
+ makeNaN(false, sign);
+ else
+ category = fcInfinity;
+ return static_cast<opStatus>(opOverflow | opInexact);
+ }
}
/* Otherwise we become the largest finite number. */
@@ -3518,13 +3541,15 @@ APInt IEEEFloat::convertIEEEFloatToAPInt() const {
myexponent = ::exponentZero(S) + bias;
mysignificand.fill(0);
} else if (category == fcInfinity) {
- if (S.nonFiniteBehavior == fltNonfiniteBehavior::NanOnly) {
+ if (S.nonFiniteBehavior == fltNonfiniteBehavior::NanOnly ||
+ S.nonFiniteBehavior == fltNonfiniteBehavior::FiniteOnly)
llvm_unreachable("semantics don't support inf!");
- }
myexponent = ::exponentInf(S) + bias;
mysignificand.fill(0);
} else {
assert(category == fcNaN && "Unknown category!");
+ if (S.nonFiniteBehavior == fltNonfiniteBehavior::FiniteOnly)
+ llvm_unreachable("semantics don't support NaN!");
myexponent = ::exponentNaN(S) + bias;
std::copy_n(significandParts(), mysignificand.size(),
mysignificand.begin());
@@ -3605,6 +3630,16 @@ APInt IEEEFloat::convertFloatTF32APFloatToAPInt() const {
return convertIEEEFloatToAPInt<semFloatTF32>();
}
+APInt IEEEFloat::convertFloat6E3M2FNAPFloatToAPInt() const {
+ assert(partCount() == 1);
+ return convertIEEEFloatToAPInt<semFloat6E3M2FN>();
+}
+
+APInt IEEEFloat::convertFloat6E2M3FNAPFloatToAPInt() const {
+ assert(partCount() == 1);
+ return convertIEEEFloatToAPInt<semFloat6E2M3FN>();
+}
+
// 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.
@@ -3646,6 +3681,12 @@ APInt IEEEFloat::bitcastToAPInt() const {
if (semantics == (const llvm::fltSemantics *)&semFloatTF32)
return convertFloatTF32APFloatToAPInt();
+ if (semantics == (const llvm::fltSemantics *)&semFloat6E3M2FN)
+ return convertFloat6E3M2FNAPFloatToAPInt();
+
+ if (semantics == (const llvm::fltSemantics *)&semFloat6E2M3FN)
+ return convertFloat6E2M3FNAPFloatToAPInt();
+
assert(semantics == (const llvm::fltSemantics*)&semX87DoubleExtended &&
"unknown format!");
return convertF80LongDoubleAPFloatToAPInt();
@@ -3862,6 +3903,14 @@ void IEEEFloat::initFromFloatTF32APInt(const APInt &api) {
initFromIEEEAPInt<semFloatTF32>(api);
}
+void IEEEFloat::initFromFloat6E3M2FNAPInt(const APInt &api) {
+ initFromIEEEAPInt<semFloat6E3M2FN>(api);
+}
+
+void IEEEFloat::initFromFloat6E2M3FNAPInt(const APInt &api) {
+ initFromIEEEAPInt<semFloat6E2M3FN>(api);
+}
+
/// 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);
@@ -3891,6 +3940,10 @@ void IEEEFloat::initFromAPInt(const fltSemantics *Sem, const APInt &api) {
return initFromFloat8E4M3B11FNUZAPInt(api);
if (Sem == &semFloatTF32)
return initFromFloatTF32APInt(api);
+ if (Sem == &semFloat6E3M2FN)
+ return initFromFloat6E3M2FNAPInt(api);
+ if (Sem == &semFloat6E2M3FN)
+ return initFromFloat6E2M3FNAPInt(api);
llvm_unreachable(nullptr);
}
@@ -4328,7 +4381,8 @@ int IEEEFloat::getExactLog2Abs() const {
bool IEEEFloat::isSignaling() const {
if (!isNaN())
return false;
- if (semantics->nonFiniteBehavior == fltNonfiniteBehavior::NanOnly)
+ if (semantics->nonFiniteBehavior == fltNonfiniteBehavior::NanOnly ||
+ semantics->nonFiniteBehavior == fltNonfiniteBehavior::FiniteOnly)
return false;
// IEEE-754R 2008 6.2.1: A signaling NaN bit string should be encoded with the
@@ -4387,6 +4441,10 @@ IEEEFloat::opStatus IEEEFloat::next(bool nextDown) {
// nextUp(getLargest()) == NAN
makeNaN();
break;
+ } else if (semantics->nonFiniteBehavior ==
+ fltNonfiniteBehavior::FiniteOnly) {
+ // nextUp(getLargest()) == getLargest()
+ break;
} else {
// nextUp(getLargest()) == INFINITY
APInt::tcSet(significandParts(), 0, partCount());
@@ -4477,6 +4535,9 @@ APFloatBase::ExponentType IEEEFloat::exponentZero() const {
}
void IEEEFloat::makeInf(bool Negative) {
+ if (semantics->nonFiniteBehavior == fltNonfiniteBehavior::FiniteOnly)
+ llvm_unreachable("This floating point format does not support Inf");
+
if (semantics->nonFiniteBehavior == fltNonfiniteBehavior::NanOnly) {
// There is no Inf, so make NaN instead.
makeNaN(false, Negative);