diff --git a/llvm/include/llvm/ADT/APFloat.h b/llvm/include/llvm/ADT/APFloat.h index 4ca928bf4f49..bf80fa5a0658 100644 --- a/llvm/include/llvm/ADT/APFloat.h +++ b/llvm/include/llvm/ADT/APFloat.h @@ -155,7 +155,41 @@ struct APFloatBase { S_IEEEsingle, S_IEEEdouble, S_IEEEquad, + // The IBM double-double semantics. Such a number consists of a pair of + // IEEE 64-bit doubles (Hi, Lo), where |Hi| > |Lo|, and if normal, + // (double)(Hi + Lo) == Hi. The numeric value it's modeling is Hi + Lo. + // Therefore it has two 53-bit mantissa parts that aren't necessarily + // adjacent to each other, and two 11-bit exponents. + // + // Note: we need to make the value different from semBogus as otherwise + // an unsafe optimization may collapse both values to a single address, + // and we heavily rely on them having distinct addresses. S_PPCDoubleDouble, + // These are legacy semantics for the fallback, inaccurate implementation + // of IBM double-double, if the accurate semPPCDoubleDouble doesn't handle + // the operation. It's equivalent to having an IEEE number with consecutive + // 106 bits of mantissa and 11 bits of exponent. + // + // It's not equivalent to IBM double-double. For example, a legit IBM + // double-double, 1 + epsilon: + // + // 1 + epsilon = 1 + (1 >> 1076) + // + // is not representable by a consecutive 106 bits of mantissa. + // + // Currently, these semantics are used in the following way: + // + // semPPCDoubleDouble -> (IEEEdouble, IEEEdouble) -> + // (64-bit APInt, 64-bit APInt) -> (128-bit APInt) -> + // semPPCDoubleDoubleLegacy -> IEEE operations + // + // We use bitcastToAPInt() to get the bit representation (in APInt) of the + // underlying IEEEdouble, then use the APInt constructor to construct the + // legacy IEEE float. + // + // TODO: Implement all operations in semPPCDoubleDouble, and delete these + // semantics. + S_PPCDoubleDoubleLegacy, // 8-bit floating point number following IEEE-754 conventions with bit // layout S1E5M2 as described in https://arxiv.org/abs/2209.05433. S_Float8E5M2, @@ -214,7 +248,7 @@ struct APFloatBase { // types, there are no infinity or NaN values. The format is detailed in // https://www.opencompute.org/documents/ocp-microscaling-formats-mx-v1-0-spec-final-pdf S_Float4E2M1FN, - + // TODO: Documentation is missing. S_x87DoubleExtended, S_MaxSemantics = S_x87DoubleExtended, }; @@ -228,6 +262,7 @@ struct APFloatBase { static const fltSemantics &IEEEdouble() LLVM_READNONE; static const fltSemantics &IEEEquad() LLVM_READNONE; static const fltSemantics &PPCDoubleDouble() LLVM_READNONE; + static const fltSemantics &PPCDoubleDoubleLegacy() LLVM_READNONE; static const fltSemantics &Float8E5M2() LLVM_READNONE; static const fltSemantics &Float8E5M2FNUZ() LLVM_READNONE; static const fltSemantics &Float8E4M3() LLVM_READNONE; @@ -688,7 +723,7 @@ private: APInt convertDoubleAPFloatToAPInt() const; APInt convertQuadrupleAPFloatToAPInt() const; APInt convertF80LongDoubleAPFloatToAPInt() const; - APInt convertPPCDoubleDoubleAPFloatToAPInt() const; + APInt convertPPCDoubleDoubleLegacyAPFloatToAPInt() const; APInt convertFloat8E5M2APFloatToAPInt() const; APInt convertFloat8E5M2FNUZAPFloatToAPInt() const; APInt convertFloat8E4M3APFloatToAPInt() const; @@ -709,7 +744,7 @@ private: void initFromDoubleAPInt(const APInt &api); void initFromQuadrupleAPInt(const APInt &api); void initFromF80LongDoubleAPInt(const APInt &api); - void initFromPPCDoubleDoubleAPInt(const APInt &api); + void initFromPPCDoubleDoubleLegacyAPInt(const APInt &api); void initFromFloat8E5M2APInt(const APInt &api); void initFromFloat8E5M2FNUZAPInt(const APInt &api); void initFromFloat8E4M3APInt(const APInt &api); diff --git a/llvm/lib/Support/APFloat.cpp b/llvm/lib/Support/APFloat.cpp index 81e297c3ab03..c9adfca8b3b7 100644 --- a/llvm/lib/Support/APFloat.cpp +++ b/llvm/lib/Support/APFloat.cpp @@ -164,42 +164,7 @@ static constexpr fltSemantics semFloat4E2M1FN = { 2, 0, 2, 4, fltNonfiniteBehavior::FiniteOnly}; static constexpr fltSemantics semX87DoubleExtended = {16383, -16382, 64, 80}; static constexpr fltSemantics semBogus = {0, 0, 0, 0}; - -/* The IBM double-double semantics. Such a number consists of a pair of IEEE - 64-bit doubles (Hi, Lo), where |Hi| > |Lo|, and if normal, - (double)(Hi + Lo) == Hi. The numeric value it's modeling is Hi + Lo. - Therefore it has two 53-bit mantissa parts that aren't necessarily adjacent - to each other, and two 11-bit exponents. - - Note: we need to make the value different from semBogus as otherwise - an unsafe optimization may collapse both values to a single address, - and we heavily rely on them having distinct addresses. */ static constexpr fltSemantics semPPCDoubleDouble = {-1, 0, 0, 128}; - -/* These are legacy semantics for the fallback, inaccrurate implementation of - IBM double-double, if the accurate semPPCDoubleDouble doesn't handle the - operation. It's equivalent to having an IEEE number with consecutive 106 - bits of mantissa and 11 bits of exponent. - - It's not equivalent to IBM double-double. For example, a legit IBM - double-double, 1 + epsilon: - - 1 + epsilon = 1 + (1 >> 1076) - - is not representable by a consecutive 106 bits of mantissa. - - Currently, these semantics are used in the following way: - - semPPCDoubleDouble -> (IEEEdouble, IEEEdouble) -> - (64-bit APInt, 64-bit APInt) -> (128-bit APInt) -> - semPPCDoubleDoubleLegacy -> IEEE operations - - We use bitcastToAPInt() to get the bit representation (in APInt) of the - underlying IEEEdouble, then use the APInt constructor to construct the - legacy IEEE float. - - TODO: Implement all operations in semPPCDoubleDouble, and delete these - semantics. */ static constexpr fltSemantics semPPCDoubleDoubleLegacy = {1023, -1022 + 53, 53 + 53, 128}; @@ -217,6 +182,8 @@ const llvm::fltSemantics &APFloatBase::EnumToSemantics(Semantics S) { return IEEEquad(); case S_PPCDoubleDouble: return PPCDoubleDouble(); + case S_PPCDoubleDoubleLegacy: + return PPCDoubleDoubleLegacy(); case S_Float8E5M2: return Float8E5M2(); case S_Float8E5M2FNUZ: @@ -261,6 +228,8 @@ APFloatBase::SemanticsToEnum(const llvm::fltSemantics &Sem) { return S_IEEEquad; else if (&Sem == &llvm::APFloat::PPCDoubleDouble()) return S_PPCDoubleDouble; + else if (&Sem == &llvm::APFloat::PPCDoubleDoubleLegacy()) + return S_PPCDoubleDoubleLegacy; else if (&Sem == &llvm::APFloat::Float8E5M2()) return S_Float8E5M2; else if (&Sem == &llvm::APFloat::Float8E5M2FNUZ()) @@ -299,6 +268,9 @@ const fltSemantics &APFloatBase::IEEEquad() { return semIEEEquad; } const fltSemantics &APFloatBase::PPCDoubleDouble() { return semPPCDoubleDouble; } +const fltSemantics &APFloatBase::PPCDoubleDoubleLegacy() { + return semPPCDoubleDoubleLegacy; +} const fltSemantics &APFloatBase::Float8E5M2() { return semFloat8E5M2; } const fltSemantics &APFloatBase::Float8E5M2FNUZ() { return semFloat8E5M2FNUZ; } const fltSemantics &APFloatBase::Float8E4M3() { return semFloat8E4M3; } @@ -3574,7 +3546,7 @@ APInt IEEEFloat::convertF80LongDoubleAPFloatToAPInt() const { return APInt(80, words); } -APInt IEEEFloat::convertPPCDoubleDoubleAPFloatToAPInt() const { +APInt IEEEFloat::convertPPCDoubleDoubleLegacyAPFloatToAPInt() const { assert(semantics == (const llvm::fltSemantics *)&semPPCDoubleDoubleLegacy); assert(partCount()==2); @@ -3796,7 +3768,7 @@ APInt IEEEFloat::bitcastToAPInt() const { return convertQuadrupleAPFloatToAPInt(); if (semantics == (const llvm::fltSemantics *)&semPPCDoubleDoubleLegacy) - return convertPPCDoubleDoubleAPFloatToAPInt(); + return convertPPCDoubleDoubleLegacyAPFloatToAPInt(); if (semantics == (const llvm::fltSemantics *)&semFloat8E5M2) return convertFloat8E5M2APFloatToAPInt(); @@ -3900,7 +3872,7 @@ void IEEEFloat::initFromF80LongDoubleAPInt(const APInt &api) { } } -void IEEEFloat::initFromPPCDoubleDoubleAPInt(const APInt &api) { +void IEEEFloat::initFromPPCDoubleDoubleLegacyAPInt(const APInt &api) { uint64_t i1 = api.getRawData()[0]; uint64_t i2 = api.getRawData()[1]; opStatus fs; @@ -4119,7 +4091,7 @@ void IEEEFloat::initFromAPInt(const fltSemantics *Sem, const APInt &api) { if (Sem == &semIEEEquad) return initFromQuadrupleAPInt(api); if (Sem == &semPPCDoubleDoubleLegacy) - return initFromPPCDoubleDoubleAPInt(api); + return initFromPPCDoubleDoubleLegacyAPInt(api); if (Sem == &semFloat8E5M2) return initFromFloat8E5M2APInt(api); if (Sem == &semFloat8E5M2FNUZ) @@ -4145,7 +4117,7 @@ void IEEEFloat::initFromAPInt(const fltSemantics *Sem, const APInt &api) { if (Sem == &semFloat4E2M1FN) return initFromFloat4E2M1FNAPInt(api); - llvm_unreachable(nullptr); + llvm_unreachable("unsupported semantics"); } /// Make this number the largest magnitude normal number in the given