From 1668bd77dfb51c719f611a46b1a31b9930fb8b3e Mon Sep 17 00:00:00 2001 From: Matthias Springer Date: Fri, 15 Nov 2024 02:58:43 +0100 Subject: [PATCH] [llvm] `APFloat`: Add helpers to query NaN/inf semantics --- llvm/include/llvm/ADT/APFloat.h | 3 ++- llvm/lib/Support/APFloat.cpp | 7 ++++++- llvm/unittests/ADT/APFloatTest.cpp | 22 ++++++++++++++++++++-- 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/llvm/include/llvm/ADT/APFloat.h b/llvm/include/llvm/ADT/APFloat.h index 4b5a85945ec17c..4ca928bf4f49e3 100644 --- a/llvm/include/llvm/ADT/APFloat.h +++ b/llvm/include/llvm/ADT/APFloat.h @@ -311,7 +311,8 @@ struct APFloatBase { static unsigned int semanticsIntSizeInBits(const fltSemantics&, bool); static bool semanticsHasZero(const fltSemantics &); static bool semanticsHasSignedRepr(const fltSemantics &); - static bool semanticsHasNanOrInf(const fltSemantics &); + static bool semanticsHasInf(const fltSemantics &); + static bool semanticsHasNaN(const fltSemantics &); // Returns true if any number described by \p Src can be precisely represented // by a normal (not subnormal) value in \p Dst. diff --git a/llvm/lib/Support/APFloat.cpp b/llvm/lib/Support/APFloat.cpp index 58bf002e0fed2e..11636bdc9b1afc 100644 --- a/llvm/lib/Support/APFloat.cpp +++ b/llvm/lib/Support/APFloat.cpp @@ -375,7 +375,12 @@ bool APFloatBase::semanticsHasSignedRepr(const fltSemantics &semantics) { return semantics.hasSignedRepr; } -bool APFloatBase::semanticsHasNanOrInf(const fltSemantics &semantics) { +bool APFloatBase::semanticsHasInf(const fltSemantics &semantics) { + return semantics.nonFiniteBehavior != fltNonfiniteBehavior::NanOnly && + semantics.nonFiniteBehavior != fltNonfiniteBehavior::FiniteOnly; +} + +bool APFloatBase::semanticsHasNaN(const fltSemantics &semantics) { return semantics.nonFiniteBehavior != fltNonfiniteBehavior::FiniteOnly; } diff --git a/llvm/unittests/ADT/APFloatTest.cpp b/llvm/unittests/ADT/APFloatTest.cpp index ab9db8ed0fa85c..d818b13e2a7e07 100644 --- a/llvm/unittests/ADT/APFloatTest.cpp +++ b/llvm/unittests/ADT/APFloatTest.cpp @@ -832,8 +832,9 @@ TEST(APFloatTest, IsSmallestNormalized) { EXPECT_FALSE(APFloat::getZero(Semantics, false).isSmallestNormalized()); EXPECT_FALSE(APFloat::getZero(Semantics, true).isSmallestNormalized()); - if (APFloat::semanticsHasNanOrInf(Semantics)) { + 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()); @@ -2557,6 +2558,14 @@ TEST(APFloatTest, isInfinity) { EXPECT_FALSE(APFloat::getNaN(APFloat::IEEEsingle(), false).isInfinity()); EXPECT_FALSE(APFloat::getSNaN(APFloat::IEEEsingle(), false).isInfinity()); EXPECT_FALSE(APFloat(APFloat::IEEEsingle(), "0x1p-149").isInfinity()); + + for (unsigned I = 0; I != APFloat::S_MaxSemantics + 1; ++I) { + const fltSemantics &Semantics = + APFloat::EnumToSemantics(static_cast(I)); + if (APFloat::semanticsHasInf(fltSemantics)) { + EXPECT_TRUE(APFloat::getInf(fltSemantics).isInfinity()); + } + } } TEST(APFloatTest, isNaN) { @@ -2567,6 +2576,14 @@ TEST(APFloatTest, isNaN) { EXPECT_TRUE(APFloat::getNaN(APFloat::IEEEsingle(), false).isNaN()); EXPECT_TRUE(APFloat::getSNaN(APFloat::IEEEsingle(), false).isNaN()); EXPECT_FALSE(APFloat(APFloat::IEEEsingle(), "0x1p-149").isNaN()); + + for (unsigned I = 0; I != APFloat::S_MaxSemantics + 1; ++I) { + const fltSemantics &Semantics = + APFloat::EnumToSemantics(static_cast(I)); + if (APFloat::semanticsHasNaN(fltSemantics)) { + EXPECT_TRUE(APFloat::getNaN(fltSemantics).isNaN()); + } + } } TEST(APFloatTest, isFiniteNonZero) { @@ -7345,8 +7362,9 @@ TEST(APFloatTest, getExactLog2) { EXPECT_EQ(INT_MIN, APFloat::getZero(Semantics, false).getExactLog2Abs()); EXPECT_EQ(INT_MIN, APFloat::getZero(Semantics, true).getExactLog2Abs()); - if (APFloat::semanticsHasNanOrInf(Semantics)) { + 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());