[llvm][NFC] APFloat: Add missing semantics to enum (#117291)

* Add missing semantics to the `Semantics` enum.
* Move all documentation of the semantics to the header file.
* Also rename some functions for consistency.
This commit is contained in:
Matthias Springer
2024-12-04 14:58:59 -08:00
committed by GitHub
parent 2fea1ccb62
commit f50ce316ec
2 changed files with 50 additions and 43 deletions

View File

@@ -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);

View File

@@ -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