diff options
Diffstat (limited to 'llvm/lib/Support/APFloat.cpp')
-rw-r--r-- | llvm/lib/Support/APFloat.cpp | 86 |
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); } |