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.cpp86
1 files changed, 74 insertions, 12 deletions
diff --git a/llvm/lib/Support/APFloat.cpp b/llvm/lib/Support/APFloat.cpp
index 6f888e31..68063bb 100644
--- a/llvm/lib/Support/APFloat.cpp
+++ b/llvm/lib/Support/APFloat.cpp
@@ -80,6 +80,7 @@ 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 semX87DoubleExtended = {16383, -16382, 64, 80};
static const fltSemantics semBogus = {0, 0, 0, 0};
@@ -131,12 +132,14 @@ 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_x87DoubleExtended:
+ return x87DoubleExtended();
}
llvm_unreachable("Unrecognised floating semantics");
}
@@ -151,12 +154,14 @@ 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::x87DoubleExtended())
+ return S_x87DoubleExtended;
else
llvm_unreachable("Unknown floating semantics");
}
@@ -173,18 +178,15 @@ 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::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;
@@ -3353,6 +3355,33 @@ 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)));
+}
+
// 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 +3405,9 @@ APInt IEEEFloat::bitcastToAPInt() const {
if (semantics == (const llvm::fltSemantics *)&semPPCDoubleDoubleLegacy)
return convertPPCDoubleDoubleAPFloatToAPInt();
+ if (semantics == (const llvm::fltSemantics *)&semFloat8E5M2)
+ return convertFloat8E5M2APFloatToAPInt();
+
assert(semantics == (const llvm::fltSemantics*)&semX87DoubleExtended &&
"unknown format!");
return convertF80LongDoubleAPFloatToAPInt();
@@ -3603,6 +3635,34 @@ void IEEEFloat::initFromHalfAPInt(const APInt &api) {
}
}
+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
+ }
+}
+
/// 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
@@ -3623,6 +3683,8 @@ void IEEEFloat::initFromAPInt(const fltSemantics *Sem, const APInt &api) {
return initFromQuadrupleAPInt(api);
if (Sem == &semPPCDoubleDoubleLegacy)
return initFromPPCDoubleDoubleAPInt(api);
+ if (Sem == &semFloat8E5M2)
+ return initFromFloat8E5M2APInt(api);
llvm_unreachable(nullptr);
}