Skip to content

Commit 78f84b6

Browse files
[LLVM][APFloat] Add APFloat support for 8-bit UE5M3 type (llvm#210720)
This commit adds APFloat support for UE5M3 type and the associated tests. It is an 8 bit FP type with no sign bit, 5 exponent and 3 mantissa bits | Property | Value | |-----------------|------------| | Max exponent | 31 | | Bias | 15 | | Zero encoding | 00000 000 | | Smallest denorm | 00000 001 | | Largest denorm | 00000 111 | | Smallest norm | 00001 000 | | Largest norm | 11111 110 | | Canonical NaN | 11111 111 | Please refer [PTX ISA](https://docs.nvidia.com/cuda/developer-preview/13.4/parallel-thread-execution/index.html#alternate-floating-point-data-formats) for more info Assisted by: Claude Code (Opus 4.8)
1 parent 1d4e04f commit 78f84b6

4 files changed

Lines changed: 376 additions & 24 deletions

File tree

‎clang/lib/AST/MicrosoftMangle.cpp‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1019,6 +1019,7 @@ void MicrosoftCXXNameMangler::mangleFloat(llvm::APFloat Number) {
10191019
case APFloat::S_Float8E3M4:
10201020
case APFloat::S_FloatTF32:
10211021
case APFloat::S_Float8E8M0FNU:
1022+
case APFloat::S_Float8E5M3FNU:
10221023
case APFloat::S_Float6E3M2FN:
10231024
case APFloat::S_Float6E2M3FN:
10241025
case APFloat::S_Float4E2M1FN:

‎llvm/include/llvm/ADT/APFloat.h‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,12 @@ class APFloatBase {
256256
// types, there are no infinity or NaN values. The format is detailed in
257257
// https://www.opencompute.org/documents/ocp-microscaling-formats-mx-v1-0-spec-final-pdf
258258
S_Float4E2M1FN,
259+
// 8-bit floating point number mostly following IEEE-754 conventions with
260+
// bit layout S0E5M3 as described in PTX ISA page.
261+
// https://docs.nvidia.com/cuda/developer-preview/13.4/parallel-thread-execution/index.html#alternate-floating-point-data-formats
262+
// Unlike IEEE-754 types, there are no infinity values, and NaN is
263+
// represented with the exponent and mantissa bits set to all 1s.
264+
S_Float8E5M3FNU,
259265
// TODO: Documentation is missing.
260266
S_x87DoubleExtended,
261267
S_MaxSemantics = S_x87DoubleExtended,
@@ -279,6 +285,7 @@ class APFloatBase {
279285
LLVM_ABI static const fltSemantics semFloat8E3M4;
280286
LLVM_ABI static const fltSemantics semFloatTF32;
281287
LLVM_ABI static const fltSemantics semFloat8E8M0FNU;
288+
LLVM_ABI static const fltSemantics semFloat8E5M3FNU;
282289
LLVM_ABI static const fltSemantics semFloat6E3M2FN;
283290
LLVM_ABI static const fltSemantics semFloat6E2M3FN;
284291
LLVM_ABI static const fltSemantics semFloat4E2M1FN;
@@ -312,6 +319,7 @@ class APFloatBase {
312319
static const fltSemantics &Float8E3M4() { return semFloat8E3M4; }
313320
static const fltSemantics &FloatTF32() { return semFloatTF32; }
314321
static const fltSemantics &Float8E8M0FNU() { return semFloat8E8M0FNU; }
322+
static const fltSemantics &Float8E5M3FNU() { return semFloat8E5M3FNU; }
315323
static const fltSemantics &Float6E3M2FN() { return semFloat6E3M2FN; }
316324
static const fltSemantics &Float6E2M3FN() { return semFloat6E2M3FN; }
317325
static const fltSemantics &Float4E2M1FN() { return semFloat4E2M1FN; }
@@ -778,6 +786,7 @@ class IEEEFloat final {
778786
APInt convertFloat8E3M4APFloatToAPInt() const;
779787
APInt convertFloatTF32APFloatToAPInt() const;
780788
APInt convertFloat8E8M0FNUAPFloatToAPInt() const;
789+
APInt convertFloat8E5M3FNUAPFloatToAPInt() const;
781790
APInt convertFloat6E3M2FNAPFloatToAPInt() const;
782791
APInt convertFloat6E2M3FNAPFloatToAPInt() const;
783792
APInt convertFloat4E2M1FNAPFloatToAPInt() const;
@@ -799,6 +808,7 @@ class IEEEFloat final {
799808
void initFromFloat8E3M4APInt(const APInt &api);
800809
void initFromFloatTF32APInt(const APInt &api);
801810
void initFromFloat8E8M0FNUAPInt(const APInt &api);
811+
void initFromFloat8E5M3FNUAPInt(const APInt &api);
802812
void initFromFloat6E3M2FNAPInt(const APInt &api);
803813
void initFromFloat6E2M3FNAPInt(const APInt &api);
804814
void initFromFloat4E2M1FNAPInt(const APInt &api);

‎llvm/lib/Support/APFloat.cpp‎

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,17 @@ constexpr fltSemantics APFloatBase::semFloat8E8M0FNU = {
9797
false,
9898
false};
9999

100+
constexpr fltSemantics APFloatBase::semFloat8E5M3FNU = {
101+
16,
102+
-14,
103+
4,
104+
8,
105+
fltNonfiniteBehavior::NanOnly,
106+
fltNanEncoding::AllOnes,
107+
true,
108+
false,
109+
false};
110+
100111
constexpr fltSemantics APFloatBase::semFloat6E3M2FN = {
101112
4, -2, 3, 6, fltNonfiniteBehavior::FiniteOnly};
102113
constexpr fltSemantics APFloatBase::semFloat6E2M3FN = {
@@ -154,6 +165,8 @@ const llvm::fltSemantics &APFloatBase::EnumToSemantics(Semantics S) {
154165
return FloatTF32();
155166
case S_Float8E8M0FNU:
156167
return Float8E8M0FNU();
168+
case S_Float8E5M3FNU:
169+
return Float8E5M3FNU();
157170
case S_Float6E3M2FN:
158171
return Float6E3M2FN();
159172
case S_Float6E2M3FN:
@@ -200,6 +213,8 @@ APFloatBase::SemanticsToEnum(const llvm::fltSemantics &Sem) {
200213
return S_FloatTF32;
201214
else if (&Sem == &llvm::APFloat::Float8E8M0FNU())
202215
return S_Float8E8M0FNU;
216+
else if (&Sem == &llvm::APFloat::Float8E5M3FNU())
217+
return S_Float8E5M3FNU;
203218
else if (&Sem == &llvm::APFloat::Float6E3M2FN())
204219
return S_Float6E3M2FN;
205220
else if (&Sem == &llvm::APFloat::Float6E2M3FN())
@@ -319,7 +334,7 @@ exponentNaN(const fltSemantics &semantics) {
319334
if (semantics.nonFiniteBehavior == fltNonfiniteBehavior::NanOnly) {
320335
if (semantics.nanEncoding == fltNanEncoding::NegativeZero)
321336
return exponentZero(semantics);
322-
if (semantics.hasSignedRepr)
337+
if (semantics.hasSignedRepr || semantics.precision > 1)
323338
return semantics.maxExponent;
324339
}
325340
return semantics.maxExponent + 1;
@@ -3575,6 +3590,11 @@ APInt IEEEFloat::convertFloat8E8M0FNUAPFloatToAPInt() const {
35753590
return convertIEEEFloatToAPInt<APFloatBase::semFloat8E8M0FNU>();
35763591
}
35773592

3593+
APInt IEEEFloat::convertFloat8E5M3FNUAPFloatToAPInt() const {
3594+
assert(partCount() == 1);
3595+
return convertIEEEFloatToAPInt<APFloatBase::semFloat8E5M3FNU>();
3596+
}
3597+
35783598
APInt IEEEFloat::convertFloat6E3M2FNAPFloatToAPInt() const {
35793599
assert(partCount() == 1);
35803600
return convertIEEEFloatToAPInt<APFloatBase::semFloat6E3M2FN>();
@@ -3642,6 +3662,9 @@ APInt IEEEFloat::bitcastToAPInt() const {
36423662
if (semantics == (const llvm::fltSemantics *)&APFloatBase::semFloat8E8M0FNU)
36433663
return convertFloat8E8M0FNUAPFloatToAPInt();
36443664

3665+
if (semantics == (const llvm::fltSemantics *)&APFloatBase::semFloat8E5M3FNU)
3666+
return convertFloat8E5M3FNUAPFloatToAPInt();
3667+
36453668
if (semantics == (const llvm::fltSemantics *)&APFloatBase::semFloat6E3M2FN)
36463669
return convertFloat6E3M2FNAPFloatToAPInt();
36473670

@@ -3716,6 +3739,10 @@ void IEEEFloat::initFromFloat8E8M0FNUAPInt(const APInt &api) {
37163739
initFromIEEEAPInt<APFloatBase::semFloat8E8M0FNU>(api);
37173740
}
37183741

3742+
void IEEEFloat::initFromFloat8E5M3FNUAPInt(const APInt &api) {
3743+
initFromIEEEAPInt<APFloatBase::semFloat8E5M3FNU>(api);
3744+
}
3745+
37193746
template <const fltSemantics &S>
37203747
void IEEEFloat::initFromIEEEAPInt(const APInt &api) {
37213748
assert(api.getBitWidth() == S.sizeInBits);
@@ -3953,6 +3980,8 @@ void IEEEFloat::initFromAPInt(const fltSemantics *Sem, const APInt &api) {
39533980
return initFromFloatTF32APInt(api);
39543981
if (Sem == &APFloatBase::semFloat8E8M0FNU)
39553982
return initFromFloat8E8M0FNUAPInt(api);
3983+
if (Sem == &APFloatBase::semFloat8E5M3FNU)
3984+
return initFromFloat8E5M3FNUAPInt(api);
39563985
if (Sem == &APFloatBase::semFloat6E3M2FN)
39573986
return initFromFloat6E3M2FNAPInt(api);
39583987
if (Sem == &APFloatBase::semFloat6E2M3FN)
@@ -6030,6 +6059,7 @@ unsigned APFloatBase::getArbitraryFPFormatSizeInBits(StringRef Format) {
60306059
.Case("Float6E3M2FN", getSizeInBits(semFloat6E3M2FN))
60316060
.Case("Float6E2M3FN", getSizeInBits(semFloat6E2M3FN))
60326061
.Case("Float4E2M1FN", getSizeInBits(semFloat4E2M1FN))
6062+
.Case("Float8E5M3FNU", getSizeInBits(semFloat8E5M3FNU))
60336063
.Default(0);
60346064
}
60356065

@@ -6039,7 +6069,8 @@ bool APFloatBase::isValidArbitraryFPFormat(StringRef Format) {
60396069

60406070
const fltSemantics *APFloatBase::getArbitraryFPSemantics(StringRef Format) {
60416071
// TODO: extend to remaining arbitrary FP types: Float8E4M3, Float8E3M4,
6042-
// Float8E5M2FNUZ, Float8E4M3FNUZ, Float8E4M3B11FNUZ, Float8E8M0FNU.
6072+
// Float8E5M2FNUZ, Float8E4M3FNUZ, Float8E4M3B11FNUZ, Float8E8M0FNU,
6073+
// Float8E5M3FNU.
60436074
return StringSwitch<const fltSemantics *>(Format)
60446075
.Case("Float8E5M2", &semFloat8E5M2)
60456076
.Case("Float8E4M3FN", &semFloat8E4M3FN)

0 commit comments

Comments
 (0)