https://github.com/schwarzschild-radius updated https://github.com/llvm/llvm-project/pull/210720
>From e5312ce9472c1ca8986ca09bc65ad2d6c40d0cc9 Mon Sep 17 00:00:00 2001 From: Pradeep Kumar <[email protected]> Date: Thu, 16 Jul 2026 02:52:46 +0000 Subject: [PATCH 1/5] [LLVM][APFloat] Add APFloat support for 8-bit UE5M3 type 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 | Assisted by: Claude Code (Opus 4.8) --- llvm/include/llvm/ADT/APFloat.h | 10 + llvm/lib/Support/APFloat.cpp | 32 +- llvm/unittests/ADT/APFloatTest.cpp | 450 +++++++++++++++++++++++++++-- 3 files changed, 461 insertions(+), 31 deletions(-) diff --git a/llvm/include/llvm/ADT/APFloat.h b/llvm/include/llvm/ADT/APFloat.h index ce94e0bacbeca..a9a3dc89a1730 100644 --- a/llvm/include/llvm/ADT/APFloat.h +++ b/llvm/include/llvm/ADT/APFloat.h @@ -256,6 +256,12 @@ class 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, + // 8-bit floating point number mostly following IEEE-754 conventions with + // bit layout S0E5M3 as described in PTX ISA page. + // https://docs.nvidia.com/cuda/developer-preview/13.4/parallel-thread-execution/index.html#alternate-floating-point-data-formats + // Unlike IEEE-754 types, there are no infinity values, and NaN is + // represented with the exponent and mantissa bits set to all 1s. + S_Float8E5M3FNU, // TODO: Documentation is missing. S_x87DoubleExtended, S_MaxSemantics = S_x87DoubleExtended, @@ -279,6 +285,7 @@ class APFloatBase { LLVM_ABI static const fltSemantics semFloat8E3M4; LLVM_ABI static const fltSemantics semFloatTF32; LLVM_ABI static const fltSemantics semFloat8E8M0FNU; + LLVM_ABI static const fltSemantics semFloat8E5M3FNU; LLVM_ABI static const fltSemantics semFloat6E3M2FN; LLVM_ABI static const fltSemantics semFloat6E2M3FN; LLVM_ABI static const fltSemantics semFloat4E2M1FN; @@ -312,6 +319,7 @@ class APFloatBase { static const fltSemantics &Float8E3M4() { return semFloat8E3M4; } static const fltSemantics &FloatTF32() { return semFloatTF32; } static const fltSemantics &Float8E8M0FNU() { return semFloat8E8M0FNU; } + static const fltSemantics &Float8E5M3FNU() { return semFloat8E5M3FNU; } static const fltSemantics &Float6E3M2FN() { return semFloat6E3M2FN; } static const fltSemantics &Float6E2M3FN() { return semFloat6E2M3FN; } static const fltSemantics &Float4E2M1FN() { return semFloat4E2M1FN; } @@ -778,6 +786,7 @@ class IEEEFloat final { APInt convertFloat8E3M4APFloatToAPInt() const; APInt convertFloatTF32APFloatToAPInt() const; APInt convertFloat8E8M0FNUAPFloatToAPInt() const; + APInt convertFloat8E5M3FNUAPFloatToAPInt() const; APInt convertFloat6E3M2FNAPFloatToAPInt() const; APInt convertFloat6E2M3FNAPFloatToAPInt() const; APInt convertFloat4E2M1FNAPFloatToAPInt() const; @@ -799,6 +808,7 @@ class IEEEFloat final { void initFromFloat8E3M4APInt(const APInt &api); void initFromFloatTF32APInt(const APInt &api); void initFromFloat8E8M0FNUAPInt(const APInt &api); + void initFromFloat8E5M3FNUAPInt(const APInt &api); void initFromFloat6E3M2FNAPInt(const APInt &api); void initFromFloat6E2M3FNAPInt(const APInt &api); void initFromFloat4E2M1FNAPInt(const APInt &api); diff --git a/llvm/lib/Support/APFloat.cpp b/llvm/lib/Support/APFloat.cpp index 74f7803c43e67..2fe1ede16fda4 100644 --- a/llvm/lib/Support/APFloat.cpp +++ b/llvm/lib/Support/APFloat.cpp @@ -97,6 +97,17 @@ constexpr fltSemantics APFloatBase::semFloat8E8M0FNU = { false, false}; +constexpr fltSemantics APFloatBase::semFloat8E5M3FNU = { + 16, + -14, + 4, + 8, + fltNonfiniteBehavior::NanOnly, + fltNanEncoding::AllOnes, + true, + false, + false}; + constexpr fltSemantics APFloatBase::semFloat6E3M2FN = { 4, -2, 3, 6, fltNonfiniteBehavior::FiniteOnly}; constexpr fltSemantics APFloatBase::semFloat6E2M3FN = { @@ -154,6 +165,8 @@ const llvm::fltSemantics &APFloatBase::EnumToSemantics(Semantics S) { return FloatTF32(); case S_Float8E8M0FNU: return Float8E8M0FNU(); + case S_Float8E5M3FNU: + return Float8E5M3FNU(); case S_Float6E3M2FN: return Float6E3M2FN(); case S_Float6E2M3FN: @@ -200,6 +213,8 @@ APFloatBase::SemanticsToEnum(const llvm::fltSemantics &Sem) { return S_FloatTF32; else if (&Sem == &llvm::APFloat::Float8E8M0FNU()) return S_Float8E8M0FNU; + else if (&Sem == &llvm::APFloat::Float8E5M3FNU()) + return S_Float8E5M3FNU; else if (&Sem == &llvm::APFloat::Float6E3M2FN()) return S_Float6E3M2FN; else if (&Sem == &llvm::APFloat::Float6E2M3FN()) @@ -319,7 +334,7 @@ exponentNaN(const fltSemantics &semantics) { if (semantics.nonFiniteBehavior == fltNonfiniteBehavior::NanOnly) { if (semantics.nanEncoding == fltNanEncoding::NegativeZero) return exponentZero(semantics); - if (semantics.hasSignedRepr) + if (semantics.hasSignedRepr || semantics.precision > 1) return semantics.maxExponent; } return semantics.maxExponent + 1; @@ -3575,6 +3590,11 @@ APInt IEEEFloat::convertFloat8E8M0FNUAPFloatToAPInt() const { return convertIEEEFloatToAPInt<APFloatBase::semFloat8E8M0FNU>(); } +APInt IEEEFloat::convertFloat8E5M3FNUAPFloatToAPInt() const { + assert(partCount() == 1); + return convertIEEEFloatToAPInt<APFloatBase::semFloat8E5M3FNU>(); +} + APInt IEEEFloat::convertFloat6E3M2FNAPFloatToAPInt() const { assert(partCount() == 1); return convertIEEEFloatToAPInt<APFloatBase::semFloat6E3M2FN>(); @@ -3642,6 +3662,9 @@ APInt IEEEFloat::bitcastToAPInt() const { if (semantics == (const llvm::fltSemantics *)&APFloatBase::semFloat8E8M0FNU) return convertFloat8E8M0FNUAPFloatToAPInt(); + if (semantics == (const llvm::fltSemantics *)&APFloatBase::semFloat8E5M3FNU) + return convertFloat8E5M3FNUAPFloatToAPInt(); + if (semantics == (const llvm::fltSemantics *)&APFloatBase::semFloat6E3M2FN) return convertFloat6E3M2FNAPFloatToAPInt(); @@ -3716,6 +3739,10 @@ void IEEEFloat::initFromFloat8E8M0FNUAPInt(const APInt &api) { initFromIEEEAPInt<APFloatBase::semFloat8E8M0FNU>(api); } +void IEEEFloat::initFromFloat8E5M3FNUAPInt(const APInt &api) { + initFromIEEEAPInt<APFloatBase::semFloat8E5M3FNU>(api); +} + template <const fltSemantics &S> void IEEEFloat::initFromIEEEAPInt(const APInt &api) { assert(api.getBitWidth() == S.sizeInBits); @@ -3953,6 +3980,8 @@ void IEEEFloat::initFromAPInt(const fltSemantics *Sem, const APInt &api) { return initFromFloatTF32APInt(api); if (Sem == &APFloatBase::semFloat8E8M0FNU) return initFromFloat8E8M0FNUAPInt(api); + if (Sem == &APFloatBase::semFloat8E5M3FNU) + return initFromFloat8E5M3FNUAPInt(api); if (Sem == &APFloatBase::semFloat6E3M2FN) return initFromFloat6E3M2FNAPInt(api); if (Sem == &APFloatBase::semFloat6E2M3FN) @@ -6030,6 +6059,7 @@ unsigned APFloatBase::getArbitraryFPFormatSizeInBits(StringRef Format) { .Case("Float6E3M2FN", getSizeInBits(semFloat6E3M2FN)) .Case("Float6E2M3FN", getSizeInBits(semFloat6E2M3FN)) .Case("Float4E2M1FN", getSizeInBits(semFloat4E2M1FN)) + .Case("Float8E5M3FNU", getSizeInBits(semFloat8E5M3FNU)) .Default(0); } diff --git a/llvm/unittests/ADT/APFloatTest.cpp b/llvm/unittests/ADT/APFloatTest.cpp index 456a7a5ffefb9..8b80b46e3c3a8 100644 --- a/llvm/unittests/ADT/APFloatTest.cpp +++ b/llvm/unittests/ADT/APFloatTest.cpp @@ -1046,37 +1046,40 @@ TEST(APFloatTest, IsSmallestNormalized) { if (I == APFloat::S_Float8E8M0FNU) continue; - EXPECT_FALSE(APFloat::getZero(Semantics, false).isSmallestNormalized()); - EXPECT_FALSE(APFloat::getZero(Semantics, true).isSmallestNormalized()); + EXPECT_FALSE(APFloat::getZero(Semantics).isSmallestNormalized()); + if (Semantics.hasSignedRepr) + EXPECT_FALSE(APFloat::getZero(Semantics, /* Negative */ true) + .isSmallestNormalized()); if (APFloat::semanticsHasNaN(Semantics)) { // Types that do not support Inf will return NaN when asked for Inf. // (But only if they support NaN.) - EXPECT_FALSE(APFloat::getInf(Semantics, false).isSmallestNormalized()); - EXPECT_FALSE(APFloat::getInf(Semantics, true).isSmallestNormalized()); + EXPECT_FALSE(APFloat::getInf(Semantics).isSmallestNormalized()); + if (Semantics.hasSignedRepr) + EXPECT_FALSE(APFloat::getInf(Semantics, /* Negative */ true) + .isSmallestNormalized()); EXPECT_FALSE(APFloat::getQNaN(Semantics).isSmallestNormalized()); EXPECT_FALSE(APFloat::getSNaN(Semantics).isSmallestNormalized()); } EXPECT_FALSE(APFloat::getLargest(Semantics).isSmallestNormalized()); - EXPECT_FALSE(APFloat::getLargest(Semantics, true).isSmallestNormalized()); + if (Semantics.hasSignedRepr) + EXPECT_FALSE(APFloat::getLargest(Semantics, /* Negative */ true) + .isSmallestNormalized()); EXPECT_FALSE(APFloat::getSmallest(Semantics).isSmallestNormalized()); - EXPECT_FALSE(APFloat::getSmallest(Semantics, true).isSmallestNormalized()); + if (Semantics.hasSignedRepr) + EXPECT_FALSE(APFloat::getSmallest(Semantics, /* Negative */ true) + .isSmallestNormalized()); EXPECT_FALSE(APFloat::getAllOnesValue(Semantics).isSmallestNormalized()); - APFloat PosSmallestNormalized = - APFloat::getSmallestNormalized(Semantics, false); - APFloat NegSmallestNormalized = - APFloat::getSmallestNormalized(Semantics, true); + APFloat PosSmallestNormalized = APFloat::getSmallestNormalized(Semantics); EXPECT_TRUE(PosSmallestNormalized.isSmallestNormalized()); - EXPECT_TRUE(NegSmallestNormalized.isSmallestNormalized()); EXPECT_EQ(fcPosNormal, PosSmallestNormalized.classify()); - EXPECT_EQ(fcNegNormal, NegSmallestNormalized.classify()); - for (APFloat *Val : {&PosSmallestNormalized, &NegSmallestNormalized}) { + auto SmallestNormalized = [&](APFloat *Val) { bool OldSign = Val->isNegative(); // Step down, make sure it's still not smallest normalized. @@ -1094,6 +1097,15 @@ TEST(APFloatTest, IsSmallestNormalized) { EXPECT_EQ(APFloat::opOK, Val->next(true)); EXPECT_FALSE(Val->isSmallestNormalized()); EXPECT_EQ(OldSign, Val->isNegative()); + }; + + SmallestNormalized(&PosSmallestNormalized); + if (Semantics.hasSignedRepr) { + APFloat NegSmallestNormalized = + APFloat::getSmallestNormalized(Semantics, /* Negative */ true); + EXPECT_TRUE(NegSmallestNormalized.isSmallestNormalized()); + EXPECT_EQ(fcNegNormal, NegSmallestNormalized.classify()); + SmallestNormalized(&NegSmallestNormalized); } } } @@ -2308,6 +2320,8 @@ TEST(APFloatTest, getLargest) { APFloat::getLargest(APFloat::FloatTF32()).convertToFloat()); EXPECT_EQ(1.701411834e+38f, APFloat::getLargest(APFloat::Float8E8M0FNU()).convertToDouble()); + EXPECT_EQ(0x1.cp016, + APFloat::getLargest(APFloat::Float8E5M3FNU()).convertToDouble()); EXPECT_EQ(28, APFloat::getLargest(APFloat::Float6E3M2FN()).convertToDouble()); EXPECT_EQ(7.5, APFloat::getLargest(APFloat::Float6E2M3FN()).convertToDouble()); @@ -2398,6 +2412,13 @@ TEST(APFloatTest, getSmallest) { EXPECT_TRUE(test.isFiniteNonZero()); EXPECT_FALSE(test.isDenormal()); EXPECT_TRUE(test.bitwiseIsEqual(expected)); + + test = APFloat::getSmallest(APFloat::Float8E5M3FNU(), false); + expected = APFloat(APFloat::Float8E5M3FNU(), "0x1.0p-17"); + EXPECT_FALSE(test.isNegative()); + EXPECT_TRUE(test.isFiniteNonZero()); + EXPECT_TRUE(test.isDenormal()); + EXPECT_TRUE(test.bitwiseIsEqual(expected)); } TEST(APFloatTest, getSmallestNormalized) { @@ -2512,6 +2533,14 @@ TEST(APFloatTest, getSmallestNormalized) { EXPECT_FALSE(test.isDenormal()); EXPECT_TRUE(test.bitwiseIsEqual(expected)); EXPECT_TRUE(test.isSmallestNormalized()); + + test = APFloat::getSmallestNormalized(APFloat::Float8E5M3FNU(), false); + expected = APFloat(APFloat::Float8E5M3FNU(), "0x1.0p-14"); + EXPECT_FALSE(test.isNegative()); + EXPECT_TRUE(test.isFiniteNonZero()); + EXPECT_FALSE(test.isDenormal()); + EXPECT_TRUE(test.bitwiseIsEqual(expected)); + EXPECT_TRUE(test.isSmallestNormalized()); } TEST(APFloatTest, getZero) { @@ -2538,6 +2567,7 @@ TEST(APFloatTest, getZero) { {&APFloat::Float8E5M2(), true, true, {0x80ULL, 0}, 1}, {&APFloat::Float8E5M2FNUZ(), false, false, {0, 0}, 1}, {&APFloat::Float8E5M2FNUZ(), true, false, {0, 0}, 1}, + {&APFloat::Float8E5M3FNU(), false, false, {0, 0}, 1}, {&APFloat::Float8E4M3(), false, true, {0, 0}, 1}, {&APFloat::Float8E4M3(), true, true, {0x80ULL, 0}, 1}, {&APFloat::Float8E4M3FN(), false, true, {0, 0}, 1}, @@ -9535,9 +9565,11 @@ TEST(APFloatTest, getExactLog2) { EXPECT_EQ(0, One.getExactLog2()); EXPECT_EQ(INT_MIN, APFloat(Semantics, "3.0").getExactLog2()); - EXPECT_EQ(INT_MIN, APFloat(Semantics, "-3.0").getExactLog2()); EXPECT_EQ(INT_MIN, APFloat(Semantics, "3.0").getExactLog2Abs()); - EXPECT_EQ(INT_MIN, APFloat(Semantics, "-3.0").getExactLog2Abs()); + if (Semantics.hasSignedRepr) { + EXPECT_EQ(INT_MIN, APFloat(Semantics, "-3.0").getExactLog2()); + EXPECT_EQ(INT_MIN, APFloat(Semantics, "-3.0").getExactLog2Abs()); + } if (I == APFloat::S_Float6E2M3FN || I == APFloat::S_Float4E2M1FN) { EXPECT_EQ(2, APFloat(Semantics, "4.0").getExactLog2()); @@ -9546,32 +9578,52 @@ TEST(APFloatTest, getExactLog2) { EXPECT_EQ(2, APFloat(Semantics, "-4.0").getExactLog2Abs()); } else { EXPECT_EQ(3, APFloat(Semantics, "8.0").getExactLog2()); - EXPECT_EQ(INT_MIN, APFloat(Semantics, "-8.0").getExactLog2()); EXPECT_EQ(-2, APFloat(Semantics, "0.25").getExactLog2()); EXPECT_EQ(-2, APFloat(Semantics, "0.25").getExactLog2Abs()); - EXPECT_EQ(INT_MIN, APFloat(Semantics, "-0.25").getExactLog2()); - EXPECT_EQ(-2, APFloat(Semantics, "-0.25").getExactLog2Abs()); - EXPECT_EQ(3, APFloat(Semantics, "8.0").getExactLog2Abs()); - EXPECT_EQ(3, APFloat(Semantics, "-8.0").getExactLog2Abs()); + if (Semantics.hasSignedRepr) { + EXPECT_EQ(INT_MIN, APFloat(Semantics, "-8.0").getExactLog2()); + EXPECT_EQ(INT_MIN, APFloat(Semantics, "-0.25").getExactLog2()); + EXPECT_EQ(-2, APFloat(Semantics, "-0.25").getExactLog2Abs()); + EXPECT_EQ(3, APFloat(Semantics, "8.0").getExactLog2Abs()); + EXPECT_EQ(3, APFloat(Semantics, "-8.0").getExactLog2Abs()); + } } - EXPECT_EQ(INT_MIN, APFloat::getZero(Semantics, false).getExactLog2()); - EXPECT_EQ(INT_MIN, APFloat::getZero(Semantics, true).getExactLog2()); - EXPECT_EQ(INT_MIN, APFloat::getZero(Semantics, false).getExactLog2Abs()); - EXPECT_EQ(INT_MIN, APFloat::getZero(Semantics, true).getExactLog2Abs()); + EXPECT_EQ(INT_MIN, APFloat::getZero(Semantics).getExactLog2()); + EXPECT_EQ(INT_MIN, APFloat::getZero(Semantics).getExactLog2Abs()); + if (Semantics.hasSignedRepr) { + EXPECT_EQ( + INT_MIN, + APFloat::getZero(Semantics, /* Negative */ true).getExactLog2()); + EXPECT_EQ( + INT_MIN, + APFloat::getZero(Semantics, /* Negative */ true).getExactLog2Abs()); + } if (APFloat::semanticsHasNaN(Semantics)) { // Types that do not support Inf will return NaN when asked for Inf. // (But only if they support NaN.) EXPECT_EQ(INT_MIN, APFloat::getInf(Semantics).getExactLog2()); - EXPECT_EQ(INT_MIN, APFloat::getInf(Semantics, true).getExactLog2()); - EXPECT_EQ(INT_MIN, APFloat::getNaN(Semantics, false).getExactLog2()); - EXPECT_EQ(INT_MIN, APFloat::getNaN(Semantics, true).getExactLog2()); + EXPECT_EQ(INT_MIN, APFloat::getNaN(Semantics).getExactLog2()); + if (Semantics.hasSignedRepr) { + EXPECT_EQ( + INT_MIN, + APFloat::getInf(Semantics, /* Negative */ true).getExactLog2()); + EXPECT_EQ( + INT_MIN, + APFloat::getNaN(Semantics, /* Negative */ true).getExactLog2()); + } EXPECT_EQ(INT_MIN, APFloat::getInf(Semantics).getExactLog2Abs()); - EXPECT_EQ(INT_MIN, APFloat::getInf(Semantics, true).getExactLog2Abs()); - EXPECT_EQ(INT_MIN, APFloat::getNaN(Semantics, false).getExactLog2Abs()); - EXPECT_EQ(INT_MIN, APFloat::getNaN(Semantics, true).getExactLog2Abs()); + EXPECT_EQ(INT_MIN, APFloat::getNaN(Semantics).getExactLog2Abs()); + if (Semantics.hasSignedRepr) { + EXPECT_EQ( + INT_MIN, + APFloat::getInf(Semantics, /* Negative */ true).getExactLog2Abs()); + EXPECT_EQ( + INT_MIN, + APFloat::getNaN(Semantics, /* Negative */ true).getExactLog2Abs()); + } } EXPECT_EQ( @@ -9860,6 +9912,342 @@ TEST(APFloatTest, ConvertDoubleToE8M0FNU) { EXPECT_EQ(status, APFloat::opUnderflow | APFloat::opInexact); } +TEST(APFloatTest, Float8E5M3FNUValues) { + // High end of the range + auto test = APFloat(APFloat::Float8E5M3FNU(), "0x1.c0p16"); + EXPECT_EQ(0x1.c0p16, test.convertToDouble()); + + test = APFloat(APFloat::Float8E5M3FNU(), "0x1.c0p15"); + EXPECT_EQ(0x1.cp15, test.convertToDouble()); + + test = APFloat(APFloat::Float8E5M3FNU(), "0x1.0p14"); + EXPECT_EQ(0x1.0p14, test.convertToDouble()); + + // tests the fix in makeLargest() + test = APFloat::getLargest(APFloat::Float8E5M3FNU()); + EXPECT_EQ(0x1.cp16, test.convertToDouble()); + + // tests overflow to nan + APFloat nan = APFloat(APFloat::Float8E5M3FNU(), "nan"); + test = APFloat(APFloat::Float8E5M3FNU(), "0x1.e0p+16"); + EXPECT_TRUE(test.bitwiseIsEqual(nan)); + + // Mid of the range + test = APFloat(APFloat::Float8E5M3FNU(), "0x1.0p0"); + EXPECT_EQ(1.0, test.convertToDouble()); + + test = APFloat(APFloat::Float8E5M3FNU(), "0x1.0p1"); + EXPECT_EQ(2.0, test.convertToDouble()); + + test = APFloat(APFloat::Float8E5M3FNU(), "0x1.0p2"); + EXPECT_EQ(4.0, test.convertToDouble()); + + // Low end of the range + test = APFloat(APFloat::Float8E5M3FNU(), "0x1.0p-12"); + EXPECT_EQ(0x1.0p-12, test.convertToDouble()); + + test = APFloat(APFloat::Float8E5M3FNU(), "0x1.0p-13"); + EXPECT_EQ(0x1.0p-13, test.convertToDouble()); + + test = APFloat(APFloat::Float8E5M3FNU(), "0x1.0p-14"); + EXPECT_EQ(0x1.0p-14, test.convertToDouble()); + EXPECT_TRUE(test.isSmallestNormalized()); + + // Smallest value + test = APFloat::getSmallest(APFloat::Float8E5M3FNU()); + EXPECT_EQ(0x1.0p-17, test.convertToDouble()); + + // Value below the smallest, but clamped to the smallest + test = APFloat(APFloat::Float8E5M3FNU(), "0x1.0p-18"); + EXPECT_EQ(0, test.convertToDouble()); +} + +TEST(APFloatTest, Float8E5M3FNUFromString) { + // Exactly representable + EXPECT_EQ(64, APFloat(APFloat::Float8E5M3FNU(), "64").convertToDouble()); + // Overflow to NaN + EXPECT_TRUE(APFloat(APFloat::Float8E5M3FNU(), "0x1.0p17").isNaN()); + // Inf converted to NaN + EXPECT_TRUE(APFloat(APFloat::Float8E5M3FNU(), "inf").isNaN()); + // NaN converted to NaN + EXPECT_TRUE(APFloat(APFloat::Float8E5M3FNU(), "nan").isNaN()); +} + +TEST(APFloatTest, Float8E5M3FNUDivideByZero) { + APFloat x(APFloat::Float8E5M3FNU(), "1"); + APFloat zero(APFloat::Float8E5M3FNU(), "0"); + EXPECT_EQ(x.divide(zero, APFloat::rmNearestTiesToEven), APFloat::opDivByZero); + EXPECT_TRUE(x.isNaN()); +} + +TEST(APFloatTest, Float8E5M3FNUGetSignedValues) { +#ifdef GTEST_HAS_DEATH_TEST +#ifndef NDEBUG + EXPECT_DEATH(APFloat(APFloat::Float8E5M3FNU(), "-64"), + "This floating point format does not support signed values"); + EXPECT_DEATH(APFloat(APFloat::Float8E5M3FNU(), "-0x1.0p17"), + "This floating point format does not support signed values"); + EXPECT_DEATH(APFloat(APFloat::Float8E5M3FNU(), "-inf"), + "This floating point format does not support signed values"); + EXPECT_DEATH(APFloat::getNaN(APFloat::Float8E5M3FNU(), true), + "This floating point format does not support signed values"); + EXPECT_DEATH(APFloat::getInf(APFloat::Float8E5M3FNU(), true), + "This floating point format does not support signed values"); + EXPECT_DEATH(APFloat::getSmallest(APFloat::Float8E5M3FNU(), true), + "This floating point format does not support signed values"); + EXPECT_DEATH(APFloat::getSmallestNormalized(APFloat::Float8E5M3FNU(), true), + "This floating point format does not support signed values"); + EXPECT_DEATH(APFloat::getLargest(APFloat::Float8E5M3FNU(), true), + "This floating point format does not support signed values"); + APFloat x = APFloat(APFloat::Float8E5M3FNU(), "4"); + APFloat y = APFloat(APFloat::Float8E5M3FNU(), "8"); + EXPECT_DEATH(x.subtract(y, APFloat::rmNearestTiesToEven), + "This floating point format does not support signed values"); +#endif // NDEBUG +#endif // GTEST_HAS_DEATH_TEST +} + +TEST(APFloatTest, Float8E5M3FNUGetInf) { + // The Float8E5M3FNU format does not support infinity and the all ones + // representation is treated as NaN. + APFloat t = APFloat::getInf(APFloat::Float8E5M3FNU()); + EXPECT_TRUE(t.isNaN()); + EXPECT_FALSE(t.isInfinity()); +} + +TEST(APFloatTest, Float8E5M3FNUSmallest) { + APFloat test(APFloat::getSmallest(APFloat::Float8E5M3FNU())); + EXPECT_EQ(0x1.0p-17, test.convertToDouble()); + + EXPECT_TRUE(test.isSmallest()); + EXPECT_EQ(fcPosSubnormal, test.classify()); + + test = APFloat::getAllOnesValue(APFloat::Float8E5M3FNU()); + EXPECT_TRUE(test.isNaN()); +} + +TEST(APFloatTest, Float8E5M3FNUExhaustivePair) { + // Test each pair of 8-bit values for Float8E5M3FNU format. + // This format is unsigned, so subtraction is only tested when the result + // is non-negative (which corresponds to i >= j since the bit-pattern + // ordering matches the value ordering). IEEE remainder can produce + // negative results, so it is only tested when the reference result is + // non-negative. + APFloat::Semantics Sem = APFloat::S_Float8E5M3FNU; + const llvm::fltSemantics &S = APFloat::EnumToSemantics(Sem); + for (int i = 0; i < 256; i++) { + for (int j = 0; j < 256; j++) { + SCOPED_TRACE("sem=" + std::to_string(Sem) + ",i=" + std::to_string(i) + + ",j=" + std::to_string(j)); + APFloat x(S, APInt(8, i)); + APFloat y(S, APInt(8, j)); + + bool losesInfo; + APFloat xd = x; + xd.convert(APFloat::IEEEdouble(), APFloat::rmNearestTiesToEven, + &losesInfo); + EXPECT_FALSE(losesInfo); + APFloat yd = y; + yd.convert(APFloat::IEEEdouble(), APFloat::rmNearestTiesToEven, + &losesInfo); + EXPECT_FALSE(losesInfo); + + // Add + APFloat z = x; + z.add(y, APFloat::rmNearestTiesToEven); + APFloat zd = xd; + zd.add(yd, APFloat::rmNearestTiesToEven); + zd.convert(S, APFloat::rmNearestTiesToEven, &losesInfo); + EXPECT_TRUE(z.bitwiseIsEqual(zd)) + << "sem=" << Sem << ", i=" << i << ", j=" << j; + + // Subtract + if (i >= j) { + z = x; + z.subtract(y, APFloat::rmNearestTiesToEven); + zd = xd; + zd.subtract(yd, APFloat::rmNearestTiesToEven); + zd.convert(S, APFloat::rmNearestTiesToEven, &losesInfo); + EXPECT_TRUE(z.bitwiseIsEqual(zd)) + << "sem=" << Sem << ", i=" << i << ", j=" << j; + } + + // Multiply + z = x; + z.multiply(y, APFloat::rmNearestTiesToEven); + zd = xd; + zd.multiply(yd, APFloat::rmNearestTiesToEven); + zd.convert(S, APFloat::rmNearestTiesToEven, &losesInfo); + EXPECT_TRUE(z.bitwiseIsEqual(zd)) + << "sem=" << Sem << ", i=" << i << ", j=" << j; + + // Divide + z = x; + z.divide(y, APFloat::rmNearestTiesToEven); + zd = xd; + zd.divide(yd, APFloat::rmNearestTiesToEven); + zd.convert(S, APFloat::rmNearestTiesToEven, &losesInfo); + EXPECT_TRUE(z.bitwiseIsEqual(zd)) + << "sem=" << Sem << ", i=" << i << ", j=" << j; + + // Mod + z = x; + z.mod(y); + zd = xd; + zd.mod(yd); + zd.convert(S, APFloat::rmNearestTiesToEven, &losesInfo); + EXPECT_TRUE(z.bitwiseIsEqual(zd)) + << "sem=" << Sem << ", i=" << i << ", j=" << j; + + // Remainder: IEEE remainder can produce negative results, which this + // unsigned format cannot represent. Only test when the reference + // result is non-negative. + zd = xd; + zd.remainder(yd); + if (!zd.isNegative()) { + z = x; + z.remainder(y); + zd.convert(S, APFloat::rmNearestTiesToEven, &losesInfo); + EXPECT_TRUE(z.bitwiseIsEqual(zd)) + << "sem=" << Sem << ", i=" << i << ", j=" << j; + } + } + } +} + +TEST(APFloatTest, Float8E5M3FNUExhaustive) { + // Test each of the 256 Float8E5M3FNU values. + // Layout: 5 exponent bits + 3 mantissa bits, bias = 15, NaN = 0xFF + // (all-ones). + for (int i = 0; i < 256; i++) { + APFloat test(APFloat::Float8E5M3FNU(), APInt(8, i)); + SCOPED_TRACE("i=" + std::to_string(i)); + + // bitcastToAPInt + EXPECT_EQ(i, test.bitcastToAPInt()); + + // isLargest + if (i == 254) { + EXPECT_TRUE(test.isLargest()); + EXPECT_EQ(test.convertToDouble(), 0x1.cp16); + } else { + EXPECT_FALSE(test.isLargest()); + } + + // isSmallest (smallest positive subnormal: bit pattern 0x01 = 2^-17) + if (i == 1) { + EXPECT_TRUE(test.isSmallest()); + EXPECT_EQ(test.convertToDouble(), 0x1.0p-17); + } else { + EXPECT_FALSE(test.isSmallest()); + } + + // NaN is the all-ones bit pattern. + if (i == 255) { + EXPECT_TRUE(test.isNaN()); + continue; + } + + // convert to Double + bool losesInfo; + APFloat::opStatus status = test.convert( + APFloat::IEEEdouble(), APFloat::rmNearestTiesToEven, &losesInfo); + EXPECT_EQ(status, APFloat::opOK); + EXPECT_FALSE(losesInfo); + + // Expected value: + // i == 0 -> +0 + // 1..7 -> subnormal: i * 2^-17 + // 8..254 -> normal: (1 + (i & 7)/8) * 2^((i >> 3) - 15) + double expected; + if (i == 0) + expected = 0.0; + else if (i < 8) + expected = std::ldexp(static_cast<double>(i), -17); + else + expected = std::ldexp(1.0 + (i & 7) / 8.0, (i >> 3) - 15); + EXPECT_EQ(test.convertToDouble(), expected); + } +} + +TEST(APFloatTest, Float8E5M3FNUGetExactLog2) { + const fltSemantics &Semantics = APFloat::Float8E5M3FNU(); + APFloat One(Semantics, "1.0"); + EXPECT_EQ(0, One.getExactLog2()); + + // 3.0 is exactly representable (1.5 * 2^1) but not a power of two. + EXPECT_EQ(INT_MIN, APFloat(Semantics, "3.0").getExactLog2()); + + // Exact power-of-two value. + EXPECT_EQ(3, APFloat(Semantics, "8.0").getExactLog2()); + EXPECT_EQ(3, APFloat(Semantics, "8.0").getExactLog2Abs()); + + // Negative exponent value. + EXPECT_EQ(-2, APFloat(Semantics, "0.25").getExactLog2()); + EXPECT_EQ(-2, APFloat(Semantics, "0.25").getExactLog2Abs()); + + int MinExp = APFloat::semanticsMinExponent(Semantics); + int MaxExp = APFloat::semanticsMaxExponent(Semantics); + int Precision = APFloat::semanticsPrecision(Semantics); + + // Values above the maxExp overflow to NaN, and getExactLog2() returns + // INT_MIN for these cases. + EXPECT_EQ( + INT_MIN, + scalbn(One, MaxExp + 1, APFloat::rmNearestTiesToEven).getExactLog2()); + + // This format can represent all powers of two in [MinExp - Precision + 1, + // MaxExp], including subnormal powers (2^-17, 2^-16, 2^-15). + for (int i = MinExp - Precision + 1; i <= MaxExp; ++i) { + EXPECT_EQ(i, scalbn(One, i, APFloat::rmNearestTiesToEven).getExactLog2()); + } +} + +TEST(APFloatTest, Float8E5M3FNUNext) { + APFloat test(APFloat::getSmallest(APFloat::Float8E5M3FNU())); + // Smallest positive value is the smallest subnormal: 2^-17. + EXPECT_EQ(0x1.0p-17, test.convertToDouble()); + + // Increment of 1 should reach the next subnormal: 2^-16. + EXPECT_EQ(APFloat::opOK, test.next(false)); + EXPECT_FALSE(test.isSmallest()); + EXPECT_EQ(0x1.0p-16, test.convertToDouble()); + + // Decrement of 1 should return to the smallest subnormal. + EXPECT_EQ(APFloat::opOK, test.next(true)); + EXPECT_TRUE(test.isSmallest()); + + // Decrement again should reach +0. + EXPECT_EQ(APFloat::opOK, test.next(true)); + EXPECT_TRUE(test.isPosZero()); +} + +TEST(APFloatTest, Float8E5M3FNUFMA) { + APFloat f1(APFloat::Float8E5M3FNU(), "4.0"); + APFloat f2(APFloat::Float8E5M3FNU(), "2.0"); + APFloat f3(APFloat::Float8E5M3FNU(), "8.0"); + + // Exact value: 4*2 + 8 = 16. + f1.fusedMultiplyAdd(f2, f3, APFloat::rmNearestTiesToEven); + EXPECT_EQ(16.0, f1.convertToDouble()); + + // 4*2 + 4 = 12 (exactly representable with 3 mantissa bits). + f1 = APFloat(APFloat::Float8E5M3FNU(), "4.0"); + f1.fusedMultiplyAdd(f2, f1, APFloat::rmNearestTiesToEven); + EXPECT_EQ(12.0, f1.convertToDouble()); + + // 4*8 + 2 = 34. At exponent 5 the step is 4, so 34 ties between 32 and + // 36 and rounds to 32 under round-to-nearest-even. + f1 = APFloat(APFloat::Float8E5M3FNU(), "4.0"); + f1.fusedMultiplyAdd(f3, f2, APFloat::rmNearestTiesToEven); + EXPECT_EQ(32.0, f1.convertToDouble()); + + // All of them using the same value: 1*1 + 1 = 2. + f1 = APFloat(APFloat::Float8E5M3FNU(), "1.0"); + f1.fusedMultiplyAdd(f1, f1, APFloat::rmNearestTiesToEven); + EXPECT_EQ(2.0, f1.convertToDouble()); +} + TEST(APFloatTest, Float6E3M2FNFromString) { // Exactly representable EXPECT_EQ(28, APFloat(APFloat::Float6E3M2FN(), "28").convertToDouble()); @@ -10369,6 +10757,7 @@ TEST(APFloatTest, hasSignBitInMSB) { EXPECT_TRUE(APFloat::hasSignBitInMSB(APFloat::PPCDoubleDouble())); EXPECT_TRUE(APFloat::hasSignBitInMSB(APFloat::IEEEquad())); EXPECT_FALSE(APFloat::hasSignBitInMSB(APFloat::Float8E8M0FNU())); + EXPECT_FALSE(APFloat::hasSignBitInMSB(APFloat::Float8E5M3FNU())); } TEST(APFloatTest, FrexpQuietSNaN) { @@ -10391,6 +10780,7 @@ TEST(APFloatTest, isValidArbitraryFPFormat) { EXPECT_TRUE(APFloat::isValidArbitraryFPFormat("Float6E3M2FN")); EXPECT_TRUE(APFloat::isValidArbitraryFPFormat("Float6E2M3FN")); EXPECT_TRUE(APFloat::isValidArbitraryFPFormat("Float4E2M1FN")); + EXPECT_TRUE(APFloat::isValidArbitraryFPFormat("Float8E5M3FNU")); // Test invalid format strings. EXPECT_FALSE(APFloat::isValidArbitraryFPFormat("")); >From fa628dcb7a00e3c841096326146cb215c00c38ce Mon Sep 17 00:00:00 2001 From: Pradeep Kumar <[email protected]> Date: Mon, 20 Jul 2026 16:33:45 +0000 Subject: [PATCH 2/5] Fix clang build failure due to missing default case --- clang/lib/AST/MicrosoftMangle.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp index 59732ff0fed11..5efbe3c3d8262 100644 --- a/clang/lib/AST/MicrosoftMangle.cpp +++ b/clang/lib/AST/MicrosoftMangle.cpp @@ -1019,9 +1019,11 @@ void MicrosoftCXXNameMangler::mangleFloat(llvm::APFloat Number) { case APFloat::S_Float8E3M4: case APFloat::S_FloatTF32: case APFloat::S_Float8E8M0FNU: + case APFloat::S_Float8E5M3FNU: case APFloat::S_Float6E3M2FN: case APFloat::S_Float6E2M3FN: case APFloat::S_Float4E2M1FN: + default: llvm_unreachable("Tried to mangle unexpected APFloat semantics"); } >From c4df068f79ea2865bb32a7070cd36255d58a614b Mon Sep 17 00:00:00 2001 From: Pradeep Kumar <[email protected]> Date: Mon, 20 Jul 2026 16:34:38 +0000 Subject: [PATCH 3/5] Fix formatting issues in APFloatTest file --- llvm/unittests/ADT/APFloatTest.cpp | 71 +++++++++++++++++------------- 1 file changed, 41 insertions(+), 30 deletions(-) diff --git a/llvm/unittests/ADT/APFloatTest.cpp b/llvm/unittests/ADT/APFloatTest.cpp index 8b80b46e3c3a8..342663297af6d 100644 --- a/llvm/unittests/ADT/APFloatTest.cpp +++ b/llvm/unittests/ADT/APFloatTest.cpp @@ -1046,36 +1046,41 @@ TEST(APFloatTest, IsSmallestNormalized) { if (I == APFloat::S_Float8E8M0FNU) continue; - EXPECT_FALSE(APFloat::getZero(Semantics).isSmallestNormalized()); + EXPECT_FALSE( + APFloat::getZero(Semantics, /*Negative=*/false).isSmallestNormalized()); if (Semantics.hasSignedRepr) - EXPECT_FALSE(APFloat::getZero(Semantics, /* Negative */ true) + EXPECT_FALSE(APFloat::getZero(Semantics, /*Negative=*/true) .isSmallestNormalized()); if (APFloat::semanticsHasNaN(Semantics)) { // Types that do not support Inf will return NaN when asked for Inf. // (But only if they support NaN.) - EXPECT_FALSE(APFloat::getInf(Semantics).isSmallestNormalized()); + EXPECT_FALSE(APFloat::getInf(Semantics, /*Negative=*/false) + .isSmallestNormalized()); if (Semantics.hasSignedRepr) - EXPECT_FALSE(APFloat::getInf(Semantics, /* Negative */ true) + EXPECT_FALSE(APFloat::getInf(Semantics, /*Negative=*/true) .isSmallestNormalized()); EXPECT_FALSE(APFloat::getQNaN(Semantics).isSmallestNormalized()); EXPECT_FALSE(APFloat::getSNaN(Semantics).isSmallestNormalized()); } - EXPECT_FALSE(APFloat::getLargest(Semantics).isSmallestNormalized()); + EXPECT_FALSE(APFloat::getLargest(Semantics, /*Negative=*/false) + .isSmallestNormalized()); if (Semantics.hasSignedRepr) - EXPECT_FALSE(APFloat::getLargest(Semantics, /* Negative */ true) + EXPECT_FALSE(APFloat::getLargest(Semantics, /*Negative=*/true) .isSmallestNormalized()); - EXPECT_FALSE(APFloat::getSmallest(Semantics).isSmallestNormalized()); + EXPECT_FALSE(APFloat::getSmallest(Semantics, /*Negative=*/false) + .isSmallestNormalized()); if (Semantics.hasSignedRepr) - EXPECT_FALSE(APFloat::getSmallest(Semantics, /* Negative */ true) + EXPECT_FALSE(APFloat::getSmallest(Semantics, /*Negative=*/true) .isSmallestNormalized()); EXPECT_FALSE(APFloat::getAllOnesValue(Semantics).isSmallestNormalized()); - APFloat PosSmallestNormalized = APFloat::getSmallestNormalized(Semantics); + APFloat PosSmallestNormalized = + APFloat::getSmallestNormalized(Semantics, /*Negative=*/false); EXPECT_TRUE(PosSmallestNormalized.isSmallestNormalized()); EXPECT_EQ(fcPosNormal, PosSmallestNormalized.classify()); @@ -1102,7 +1107,7 @@ TEST(APFloatTest, IsSmallestNormalized) { SmallestNormalized(&PosSmallestNormalized); if (Semantics.hasSignedRepr) { APFloat NegSmallestNormalized = - APFloat::getSmallestNormalized(Semantics, /* Negative */ true); + APFloat::getSmallestNormalized(Semantics, /*Negative=*/true); EXPECT_TRUE(NegSmallestNormalized.isSmallestNormalized()); EXPECT_EQ(fcNegNormal, NegSmallestNormalized.classify()); SmallestNormalized(&NegSmallestNormalized); @@ -9589,40 +9594,46 @@ TEST(APFloatTest, getExactLog2) { } } - EXPECT_EQ(INT_MIN, APFloat::getZero(Semantics).getExactLog2()); - EXPECT_EQ(INT_MIN, APFloat::getZero(Semantics).getExactLog2Abs()); + EXPECT_EQ(INT_MIN, + APFloat::getZero(Semantics, /*Negative=*/false).getExactLog2()); + EXPECT_EQ( + INT_MIN, + APFloat::getZero(Semantics, /*Negative=*/false).getExactLog2Abs()); if (Semantics.hasSignedRepr) { + EXPECT_EQ(INT_MIN, + APFloat::getZero(Semantics, /*Negative=*/true).getExactLog2()); EXPECT_EQ( INT_MIN, - APFloat::getZero(Semantics, /* Negative */ true).getExactLog2()); - EXPECT_EQ( - INT_MIN, - APFloat::getZero(Semantics, /* Negative */ true).getExactLog2Abs()); + APFloat::getZero(Semantics, /*Negative=*/true).getExactLog2Abs()); } if (APFloat::semanticsHasNaN(Semantics)) { // Types that do not support Inf will return NaN when asked for Inf. // (But only if they support NaN.) - EXPECT_EQ(INT_MIN, APFloat::getInf(Semantics).getExactLog2()); - EXPECT_EQ(INT_MIN, APFloat::getNaN(Semantics).getExactLog2()); + EXPECT_EQ(INT_MIN, + APFloat::getInf(Semantics, /*Negative=*/false).getExactLog2()); + EXPECT_EQ(INT_MIN, + APFloat::getNaN(Semantics, /*Negative=*/false).getExactLog2()); if (Semantics.hasSignedRepr) { - EXPECT_EQ( - INT_MIN, - APFloat::getInf(Semantics, /* Negative */ true).getExactLog2()); - EXPECT_EQ( - INT_MIN, - APFloat::getNaN(Semantics, /* Negative */ true).getExactLog2()); + EXPECT_EQ(INT_MIN, + APFloat::getInf(Semantics, /*Negative=*/true).getExactLog2()); + EXPECT_EQ(INT_MIN, + APFloat::getNaN(Semantics, /*Negative=*/true).getExactLog2()); } - EXPECT_EQ(INT_MIN, APFloat::getInf(Semantics).getExactLog2Abs()); - EXPECT_EQ(INT_MIN, APFloat::getNaN(Semantics).getExactLog2Abs()); + EXPECT_EQ( + INT_MIN, + APFloat::getInf(Semantics, /*Negative=*/false).getExactLog2Abs()); + EXPECT_EQ( + INT_MIN, + APFloat::getNaN(Semantics, /*Negative=*/false).getExactLog2Abs()); if (Semantics.hasSignedRepr) { EXPECT_EQ( INT_MIN, - APFloat::getInf(Semantics, /* Negative */ true).getExactLog2Abs()); + APFloat::getInf(Semantics, /*Negative=*/true).getExactLog2Abs()); EXPECT_EQ( INT_MIN, - APFloat::getNaN(Semantics, /* Negative */ true).getExactLog2Abs()); + APFloat::getNaN(Semantics, /*Negative=*/true).getExactLog2Abs()); } } @@ -10035,8 +10046,8 @@ TEST(APFloatTest, Float8E5M3FNUExhaustivePair) { // non-negative. APFloat::Semantics Sem = APFloat::S_Float8E5M3FNU; const llvm::fltSemantics &S = APFloat::EnumToSemantics(Sem); - for (int i = 0; i < 256; i++) { - for (int j = 0; j < 256; j++) { + for (int i = 0; i < 256; ++i) { + for (int j = 0; j < 256; ++j) { SCOPED_TRACE("sem=" + std::to_string(Sem) + ",i=" + std::to_string(i) + ",j=" + std::to_string(j)); APFloat x(S, APInt(8, i)); >From 67a125dbf4c6e5bf9e3772714eb5360717674cb7 Mon Sep 17 00:00:00 2001 From: Pradeep Kumar <[email protected]> Date: Mon, 20 Jul 2026 18:57:02 +0000 Subject: [PATCH 4/5] Remove default case from switch inside mangleFloat --- clang/lib/AST/MicrosoftMangle.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp index 5efbe3c3d8262..a1f2b671d6216 100644 --- a/clang/lib/AST/MicrosoftMangle.cpp +++ b/clang/lib/AST/MicrosoftMangle.cpp @@ -1023,7 +1023,6 @@ void MicrosoftCXXNameMangler::mangleFloat(llvm::APFloat Number) { case APFloat::S_Float6E3M2FN: case APFloat::S_Float6E2M3FN: case APFloat::S_Float4E2M1FN: - default: llvm_unreachable("Tried to mangle unexpected APFloat semantics"); } >From 19eb2a9db5c778555ef381f1b8389a8516651203 Mon Sep 17 00:00:00 2001 From: Pradeep Kumar <[email protected]> Date: Wed, 22 Jul 2026 14:07:57 +0000 Subject: [PATCH 5/5] Fixed comments in APFloatTest.cpp --- llvm/unittests/ADT/APFloatTest.cpp | 115 ++++++----------------------- 1 file changed, 23 insertions(+), 92 deletions(-) diff --git a/llvm/unittests/ADT/APFloatTest.cpp b/llvm/unittests/ADT/APFloatTest.cpp index 342663297af6d..7276d4de77dd2 100644 --- a/llvm/unittests/ADT/APFloatTest.cpp +++ b/llvm/unittests/ADT/APFloatTest.cpp @@ -1046,41 +1046,34 @@ TEST(APFloatTest, IsSmallestNormalized) { if (I == APFloat::S_Float8E8M0FNU) continue; - EXPECT_FALSE( - APFloat::getZero(Semantics, /*Negative=*/false).isSmallestNormalized()); + EXPECT_FALSE(APFloat::getZero(Semantics, false).isSmallestNormalized()); if (Semantics.hasSignedRepr) - EXPECT_FALSE(APFloat::getZero(Semantics, /*Negative=*/true) - .isSmallestNormalized()); + EXPECT_FALSE(APFloat::getZero(Semantics, true).isSmallestNormalized()); if (APFloat::semanticsHasNaN(Semantics)) { // Types that do not support Inf will return NaN when asked for Inf. // (But only if they support NaN.) - EXPECT_FALSE(APFloat::getInf(Semantics, /*Negative=*/false) - .isSmallestNormalized()); + EXPECT_FALSE(APFloat::getInf(Semantics, false).isSmallestNormalized()); if (Semantics.hasSignedRepr) - EXPECT_FALSE(APFloat::getInf(Semantics, /*Negative=*/true) - .isSmallestNormalized()); + EXPECT_FALSE(APFloat::getInf(Semantics, true).isSmallestNormalized()); EXPECT_FALSE(APFloat::getQNaN(Semantics).isSmallestNormalized()); EXPECT_FALSE(APFloat::getSNaN(Semantics).isSmallestNormalized()); } - EXPECT_FALSE(APFloat::getLargest(Semantics, /*Negative=*/false) - .isSmallestNormalized()); + EXPECT_FALSE(APFloat::getLargest(Semantics, false).isSmallestNormalized()); if (Semantics.hasSignedRepr) - EXPECT_FALSE(APFloat::getLargest(Semantics, /*Negative=*/true) - .isSmallestNormalized()); + EXPECT_FALSE(APFloat::getLargest(Semantics, true).isSmallestNormalized()); - EXPECT_FALSE(APFloat::getSmallest(Semantics, /*Negative=*/false) - .isSmallestNormalized()); + EXPECT_FALSE(APFloat::getSmallest(Semantics, false).isSmallestNormalized()); if (Semantics.hasSignedRepr) - EXPECT_FALSE(APFloat::getSmallest(Semantics, /*Negative=*/true) - .isSmallestNormalized()); + EXPECT_FALSE( + APFloat::getSmallest(Semantics, true).isSmallestNormalized()); EXPECT_FALSE(APFloat::getAllOnesValue(Semantics).isSmallestNormalized()); APFloat PosSmallestNormalized = - APFloat::getSmallestNormalized(Semantics, /*Negative=*/false); + APFloat::getSmallestNormalized(Semantics, false); EXPECT_TRUE(PosSmallestNormalized.isSmallestNormalized()); EXPECT_EQ(fcPosNormal, PosSmallestNormalized.classify()); @@ -1107,7 +1100,7 @@ TEST(APFloatTest, IsSmallestNormalized) { SmallestNormalized(&PosSmallestNormalized); if (Semantics.hasSignedRepr) { APFloat NegSmallestNormalized = - APFloat::getSmallestNormalized(Semantics, /*Negative=*/true); + APFloat::getSmallestNormalized(Semantics, true); EXPECT_TRUE(NegSmallestNormalized.isSmallestNormalized()); EXPECT_EQ(fcNegNormal, NegSmallestNormalized.classify()); SmallestNormalized(&NegSmallestNormalized); @@ -9594,46 +9587,28 @@ TEST(APFloatTest, getExactLog2) { } } - EXPECT_EQ(INT_MIN, - APFloat::getZero(Semantics, /*Negative=*/false).getExactLog2()); - EXPECT_EQ( - INT_MIN, - APFloat::getZero(Semantics, /*Negative=*/false).getExactLog2Abs()); + EXPECT_EQ(INT_MIN, APFloat::getZero(Semantics, false).getExactLog2()); + EXPECT_EQ(INT_MIN, APFloat::getZero(Semantics, false).getExactLog2Abs()); if (Semantics.hasSignedRepr) { - EXPECT_EQ(INT_MIN, - APFloat::getZero(Semantics, /*Negative=*/true).getExactLog2()); - EXPECT_EQ( - INT_MIN, - APFloat::getZero(Semantics, /*Negative=*/true).getExactLog2Abs()); + EXPECT_EQ(INT_MIN, APFloat::getZero(Semantics, true).getExactLog2()); + EXPECT_EQ(INT_MIN, APFloat::getZero(Semantics, true).getExactLog2Abs()); } if (APFloat::semanticsHasNaN(Semantics)) { // Types that do not support Inf will return NaN when asked for Inf. // (But only if they support NaN.) - EXPECT_EQ(INT_MIN, - APFloat::getInf(Semantics, /*Negative=*/false).getExactLog2()); - EXPECT_EQ(INT_MIN, - APFloat::getNaN(Semantics, /*Negative=*/false).getExactLog2()); + EXPECT_EQ(INT_MIN, APFloat::getInf(Semantics, false).getExactLog2()); + EXPECT_EQ(INT_MIN, APFloat::getNaN(Semantics, false).getExactLog2()); if (Semantics.hasSignedRepr) { - EXPECT_EQ(INT_MIN, - APFloat::getInf(Semantics, /*Negative=*/true).getExactLog2()); - EXPECT_EQ(INT_MIN, - APFloat::getNaN(Semantics, /*Negative=*/true).getExactLog2()); + EXPECT_EQ(INT_MIN, APFloat::getInf(Semantics, true).getExactLog2()); + EXPECT_EQ(INT_MIN, APFloat::getNaN(Semantics, true).getExactLog2()); } - EXPECT_EQ( - INT_MIN, - APFloat::getInf(Semantics, /*Negative=*/false).getExactLog2Abs()); - EXPECT_EQ( - INT_MIN, - APFloat::getNaN(Semantics, /*Negative=*/false).getExactLog2Abs()); + EXPECT_EQ(INT_MIN, APFloat::getInf(Semantics, false).getExactLog2Abs()); + EXPECT_EQ(INT_MIN, APFloat::getNaN(Semantics, false).getExactLog2Abs()); if (Semantics.hasSignedRepr) { - EXPECT_EQ( - INT_MIN, - APFloat::getInf(Semantics, /*Negative=*/true).getExactLog2Abs()); - EXPECT_EQ( - INT_MIN, - APFloat::getNaN(Semantics, /*Negative=*/true).getExactLog2Abs()); + EXPECT_EQ(INT_MIN, APFloat::getInf(Semantics, true).getExactLog2Abs()); + EXPECT_EQ(INT_MIN, APFloat::getNaN(Semantics, true).getExactLog2Abs()); } } @@ -10038,12 +10013,6 @@ TEST(APFloatTest, Float8E5M3FNUSmallest) { } TEST(APFloatTest, Float8E5M3FNUExhaustivePair) { - // Test each pair of 8-bit values for Float8E5M3FNU format. - // This format is unsigned, so subtraction is only tested when the result - // is non-negative (which corresponds to i >= j since the bit-pattern - // ordering matches the value ordering). IEEE remainder can produce - // negative results, so it is only tested when the reference result is - // non-negative. APFloat::Semantics Sem = APFloat::S_Float8E5M3FNU; const llvm::fltSemantics &S = APFloat::EnumToSemantics(Sem); for (int i = 0; i < 256; ++i) { @@ -10063,7 +10032,6 @@ TEST(APFloatTest, Float8E5M3FNUExhaustivePair) { &losesInfo); EXPECT_FALSE(losesInfo); - // Add APFloat z = x; z.add(y, APFloat::rmNearestTiesToEven); APFloat zd = xd; @@ -10072,7 +10040,6 @@ TEST(APFloatTest, Float8E5M3FNUExhaustivePair) { EXPECT_TRUE(z.bitwiseIsEqual(zd)) << "sem=" << Sem << ", i=" << i << ", j=" << j; - // Subtract if (i >= j) { z = x; z.subtract(y, APFloat::rmNearestTiesToEven); @@ -10083,7 +10050,6 @@ TEST(APFloatTest, Float8E5M3FNUExhaustivePair) { << "sem=" << Sem << ", i=" << i << ", j=" << j; } - // Multiply z = x; z.multiply(y, APFloat::rmNearestTiesToEven); zd = xd; @@ -10092,7 +10058,6 @@ TEST(APFloatTest, Float8E5M3FNUExhaustivePair) { EXPECT_TRUE(z.bitwiseIsEqual(zd)) << "sem=" << Sem << ", i=" << i << ", j=" << j; - // Divide z = x; z.divide(y, APFloat::rmNearestTiesToEven); zd = xd; @@ -10101,7 +10066,6 @@ TEST(APFloatTest, Float8E5M3FNUExhaustivePair) { EXPECT_TRUE(z.bitwiseIsEqual(zd)) << "sem=" << Sem << ", i=" << i << ", j=" << j; - // Mod z = x; z.mod(y); zd = xd; @@ -10181,39 +10145,6 @@ TEST(APFloatTest, Float8E5M3FNUExhaustive) { } } -TEST(APFloatTest, Float8E5M3FNUGetExactLog2) { - const fltSemantics &Semantics = APFloat::Float8E5M3FNU(); - APFloat One(Semantics, "1.0"); - EXPECT_EQ(0, One.getExactLog2()); - - // 3.0 is exactly representable (1.5 * 2^1) but not a power of two. - EXPECT_EQ(INT_MIN, APFloat(Semantics, "3.0").getExactLog2()); - - // Exact power-of-two value. - EXPECT_EQ(3, APFloat(Semantics, "8.0").getExactLog2()); - EXPECT_EQ(3, APFloat(Semantics, "8.0").getExactLog2Abs()); - - // Negative exponent value. - EXPECT_EQ(-2, APFloat(Semantics, "0.25").getExactLog2()); - EXPECT_EQ(-2, APFloat(Semantics, "0.25").getExactLog2Abs()); - - int MinExp = APFloat::semanticsMinExponent(Semantics); - int MaxExp = APFloat::semanticsMaxExponent(Semantics); - int Precision = APFloat::semanticsPrecision(Semantics); - - // Values above the maxExp overflow to NaN, and getExactLog2() returns - // INT_MIN for these cases. - EXPECT_EQ( - INT_MIN, - scalbn(One, MaxExp + 1, APFloat::rmNearestTiesToEven).getExactLog2()); - - // This format can represent all powers of two in [MinExp - Precision + 1, - // MaxExp], including subnormal powers (2^-17, 2^-16, 2^-15). - for (int i = MinExp - Precision + 1; i <= MaxExp; ++i) { - EXPECT_EQ(i, scalbn(One, i, APFloat::rmNearestTiesToEven).getExactLog2()); - } -} - TEST(APFloatTest, Float8E5M3FNUNext) { APFloat test(APFloat::getSmallest(APFloat::Float8E5M3FNU())); // Smallest positive value is the smallest subnormal: 2^-17. _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
