Skip to content

Commit f50ce31

Browse files
[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.
1 parent 2fea1cc commit f50ce31

File tree

2 files changed

+50
-43
lines changed

2 files changed

+50
-43
lines changed

llvm/include/llvm/ADT/APFloat.h

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,41 @@ struct APFloatBase {
155155
S_IEEEsingle,
156156
S_IEEEdouble,
157157
S_IEEEquad,
158+
// The IBM double-double semantics. Such a number consists of a pair of
159+
// IEEE 64-bit doubles (Hi, Lo), where |Hi| > |Lo|, and if normal,
160+
// (double)(Hi + Lo) == Hi. The numeric value it's modeling is Hi + Lo.
161+
// Therefore it has two 53-bit mantissa parts that aren't necessarily
162+
// adjacent to each other, and two 11-bit exponents.
163+
//
164+
// Note: we need to make the value different from semBogus as otherwise
165+
// an unsafe optimization may collapse both values to a single address,
166+
// and we heavily rely on them having distinct addresses.
158167
S_PPCDoubleDouble,
168+
// These are legacy semantics for the fallback, inaccurate implementation
169+
// of IBM double-double, if the accurate semPPCDoubleDouble doesn't handle
170+
// the operation. It's equivalent to having an IEEE number with consecutive
171+
// 106 bits of mantissa and 11 bits of exponent.
172+
//
173+
// It's not equivalent to IBM double-double. For example, a legit IBM
174+
// double-double, 1 + epsilon:
175+
//
176+
// 1 + epsilon = 1 + (1 >> 1076)
177+
//
178+
// is not representable by a consecutive 106 bits of mantissa.
179+
//
180+
// Currently, these semantics are used in the following way:
181+
//
182+
// semPPCDoubleDouble -> (IEEEdouble, IEEEdouble) ->
183+
// (64-bit APInt, 64-bit APInt) -> (128-bit APInt) ->
184+
// semPPCDoubleDoubleLegacy -> IEEE operations
185+
//
186+
// We use bitcastToAPInt() to get the bit representation (in APInt) of the
187+
// underlying IEEEdouble, then use the APInt constructor to construct the
188+
// legacy IEEE float.
189+
//
190+
// TODO: Implement all operations in semPPCDoubleDouble, and delete these
191+
// semantics.
192+
S_PPCDoubleDoubleLegacy,
159193
// 8-bit floating point number following IEEE-754 conventions with bit
160194
// layout S1E5M2 as described in https://arxiv.org/abs/2209.05433.
161195
S_Float8E5M2,
@@ -214,7 +248,7 @@ struct APFloatBase {
214248
// types, there are no infinity or NaN values. The format is detailed in
215249
// https://www.opencompute.org/documents/ocp-microscaling-formats-mx-v1-0-spec-final-pdf
216250
S_Float4E2M1FN,
217-
251+
// TODO: Documentation is missing.
218252
S_x87DoubleExtended,
219253
S_MaxSemantics = S_x87DoubleExtended,
220254
};
@@ -228,6 +262,7 @@ struct APFloatBase {
228262
static const fltSemantics &IEEEdouble() LLVM_READNONE;
229263
static const fltSemantics &IEEEquad() LLVM_READNONE;
230264
static const fltSemantics &PPCDoubleDouble() LLVM_READNONE;
265+
static const fltSemantics &PPCDoubleDoubleLegacy() LLVM_READNONE;
231266
static const fltSemantics &Float8E5M2() LLVM_READNONE;
232267
static const fltSemantics &Float8E5M2FNUZ() LLVM_READNONE;
233268
static const fltSemantics &Float8E4M3() LLVM_READNONE;
@@ -688,7 +723,7 @@ class IEEEFloat final {
688723
APInt convertDoubleAPFloatToAPInt() const;
689724
APInt convertQuadrupleAPFloatToAPInt() const;
690725
APInt convertF80LongDoubleAPFloatToAPInt() const;
691-
APInt convertPPCDoubleDoubleAPFloatToAPInt() const;
726+
APInt convertPPCDoubleDoubleLegacyAPFloatToAPInt() const;
692727
APInt convertFloat8E5M2APFloatToAPInt() const;
693728
APInt convertFloat8E5M2FNUZAPFloatToAPInt() const;
694729
APInt convertFloat8E4M3APFloatToAPInt() const;
@@ -709,7 +744,7 @@ class IEEEFloat final {
709744
void initFromDoubleAPInt(const APInt &api);
710745
void initFromQuadrupleAPInt(const APInt &api);
711746
void initFromF80LongDoubleAPInt(const APInt &api);
712-
void initFromPPCDoubleDoubleAPInt(const APInt &api);
747+
void initFromPPCDoubleDoubleLegacyAPInt(const APInt &api);
713748
void initFromFloat8E5M2APInt(const APInt &api);
714749
void initFromFloat8E5M2FNUZAPInt(const APInt &api);
715750
void initFromFloat8E4M3APInt(const APInt &api);

llvm/lib/Support/APFloat.cpp

Lines changed: 12 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -164,42 +164,7 @@ static constexpr fltSemantics semFloat4E2M1FN = {
164164
2, 0, 2, 4, fltNonfiniteBehavior::FiniteOnly};
165165
static constexpr fltSemantics semX87DoubleExtended = {16383, -16382, 64, 80};
166166
static constexpr fltSemantics semBogus = {0, 0, 0, 0};
167-
168-
/* The IBM double-double semantics. Such a number consists of a pair of IEEE
169-
64-bit doubles (Hi, Lo), where |Hi| > |Lo|, and if normal,
170-
(double)(Hi + Lo) == Hi. The numeric value it's modeling is Hi + Lo.
171-
Therefore it has two 53-bit mantissa parts that aren't necessarily adjacent
172-
to each other, and two 11-bit exponents.
173-
174-
Note: we need to make the value different from semBogus as otherwise
175-
an unsafe optimization may collapse both values to a single address,
176-
and we heavily rely on them having distinct addresses. */
177167
static constexpr fltSemantics semPPCDoubleDouble = {-1, 0, 0, 128};
178-
179-
/* These are legacy semantics for the fallback, inaccrurate implementation of
180-
IBM double-double, if the accurate semPPCDoubleDouble doesn't handle the
181-
operation. It's equivalent to having an IEEE number with consecutive 106
182-
bits of mantissa and 11 bits of exponent.
183-
184-
It's not equivalent to IBM double-double. For example, a legit IBM
185-
double-double, 1 + epsilon:
186-
187-
1 + epsilon = 1 + (1 >> 1076)
188-
189-
is not representable by a consecutive 106 bits of mantissa.
190-
191-
Currently, these semantics are used in the following way:
192-
193-
semPPCDoubleDouble -> (IEEEdouble, IEEEdouble) ->
194-
(64-bit APInt, 64-bit APInt) -> (128-bit APInt) ->
195-
semPPCDoubleDoubleLegacy -> IEEE operations
196-
197-
We use bitcastToAPInt() to get the bit representation (in APInt) of the
198-
underlying IEEEdouble, then use the APInt constructor to construct the
199-
legacy IEEE float.
200-
201-
TODO: Implement all operations in semPPCDoubleDouble, and delete these
202-
semantics. */
203168
static constexpr fltSemantics semPPCDoubleDoubleLegacy = {1023, -1022 + 53,
204169
53 + 53, 128};
205170

@@ -217,6 +182,8 @@ const llvm::fltSemantics &APFloatBase::EnumToSemantics(Semantics S) {
217182
return IEEEquad();
218183
case S_PPCDoubleDouble:
219184
return PPCDoubleDouble();
185+
case S_PPCDoubleDoubleLegacy:
186+
return PPCDoubleDoubleLegacy();
220187
case S_Float8E5M2:
221188
return Float8E5M2();
222189
case S_Float8E5M2FNUZ:
@@ -261,6 +228,8 @@ APFloatBase::SemanticsToEnum(const llvm::fltSemantics &Sem) {
261228
return S_IEEEquad;
262229
else if (&Sem == &llvm::APFloat::PPCDoubleDouble())
263230
return S_PPCDoubleDouble;
231+
else if (&Sem == &llvm::APFloat::PPCDoubleDoubleLegacy())
232+
return S_PPCDoubleDoubleLegacy;
264233
else if (&Sem == &llvm::APFloat::Float8E5M2())
265234
return S_Float8E5M2;
266235
else if (&Sem == &llvm::APFloat::Float8E5M2FNUZ())
@@ -299,6 +268,9 @@ const fltSemantics &APFloatBase::IEEEquad() { return semIEEEquad; }
299268
const fltSemantics &APFloatBase::PPCDoubleDouble() {
300269
return semPPCDoubleDouble;
301270
}
271+
const fltSemantics &APFloatBase::PPCDoubleDoubleLegacy() {
272+
return semPPCDoubleDoubleLegacy;
273+
}
302274
const fltSemantics &APFloatBase::Float8E5M2() { return semFloat8E5M2; }
303275
const fltSemantics &APFloatBase::Float8E5M2FNUZ() { return semFloat8E5M2FNUZ; }
304276
const fltSemantics &APFloatBase::Float8E4M3() { return semFloat8E4M3; }
@@ -3574,7 +3546,7 @@ APInt IEEEFloat::convertF80LongDoubleAPFloatToAPInt() const {
35743546
return APInt(80, words);
35753547
}
35763548

3577-
APInt IEEEFloat::convertPPCDoubleDoubleAPFloatToAPInt() const {
3549+
APInt IEEEFloat::convertPPCDoubleDoubleLegacyAPFloatToAPInt() const {
35783550
assert(semantics == (const llvm::fltSemantics *)&semPPCDoubleDoubleLegacy);
35793551
assert(partCount()==2);
35803552

@@ -3796,7 +3768,7 @@ APInt IEEEFloat::bitcastToAPInt() const {
37963768
return convertQuadrupleAPFloatToAPInt();
37973769

37983770
if (semantics == (const llvm::fltSemantics *)&semPPCDoubleDoubleLegacy)
3799-
return convertPPCDoubleDoubleAPFloatToAPInt();
3771+
return convertPPCDoubleDoubleLegacyAPFloatToAPInt();
38003772

38013773
if (semantics == (const llvm::fltSemantics *)&semFloat8E5M2)
38023774
return convertFloat8E5M2APFloatToAPInt();
@@ -3900,7 +3872,7 @@ void IEEEFloat::initFromF80LongDoubleAPInt(const APInt &api) {
39003872
}
39013873
}
39023874

3903-
void IEEEFloat::initFromPPCDoubleDoubleAPInt(const APInt &api) {
3875+
void IEEEFloat::initFromPPCDoubleDoubleLegacyAPInt(const APInt &api) {
39043876
uint64_t i1 = api.getRawData()[0];
39053877
uint64_t i2 = api.getRawData()[1];
39063878
opStatus fs;
@@ -4119,7 +4091,7 @@ void IEEEFloat::initFromAPInt(const fltSemantics *Sem, const APInt &api) {
41194091
if (Sem == &semIEEEquad)
41204092
return initFromQuadrupleAPInt(api);
41214093
if (Sem == &semPPCDoubleDoubleLegacy)
4122-
return initFromPPCDoubleDoubleAPInt(api);
4094+
return initFromPPCDoubleDoubleLegacyAPInt(api);
41234095
if (Sem == &semFloat8E5M2)
41244096
return initFromFloat8E5M2APInt(api);
41254097
if (Sem == &semFloat8E5M2FNUZ)
@@ -4145,7 +4117,7 @@ void IEEEFloat::initFromAPInt(const fltSemantics *Sem, const APInt &api) {
41454117
if (Sem == &semFloat4E2M1FN)
41464118
return initFromFloat4E2M1FNAPInt(api);
41474119

4148-
llvm_unreachable(nullptr);
4120+
llvm_unreachable("unsupported semantics");
41494121
}
41504122

41514123
/// Make this number the largest magnitude normal number in the given

0 commit comments

Comments
 (0)