diff options
author | YunQiang Su <syq@debian.org> | 2024-06-21 11:53:08 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-06-21 11:53:08 +0800 |
commit | 89881480030f48f83af668175b70a9798edca2fb (patch) | |
tree | dcc9680d4a5d3bb7093aad3d15b4d368dd752c7a /llvm/unittests/ADT/APFloatTest.cpp | |
parent | f3c4dae6f2c44f1a7f130c4cf4b2861b62402b48 (diff) | |
download | llvm-89881480030f48f83af668175b70a9798edca2fb.zip llvm-89881480030f48f83af668175b70a9798edca2fb.tar.gz llvm-89881480030f48f83af668175b70a9798edca2fb.tar.bz2 |
Intrinsic: introduce minimumnum and maximumnum (#93841)
Currently, on different platform, the behaivor of llvm.minnum is
different if one operand is sNaN:
When we compare sNaN vs NUM:
ARM/AArch64/PowerPC: follow the IEEE754-2008's minNUM: return qNaN.
RISC-V/Hexagon follow the IEEE754-2019's minimumNumber: return NUM. X86:
Returns NUM but not same with IEEE754-2019's minimumNumber as
+0.0 is not always greater than -0.0.
MIPS/LoongArch/Generic: return NUM.
LIBCALL: returns qNaN.
So, let's introduce llvm.minmumnum/llvm.maximumnum, which always follow
IEEE754-2019's minimumNumber/maximumNumber.
Half-fix: #93033
Diffstat (limited to 'llvm/unittests/ADT/APFloatTest.cpp')
-rw-r--r-- | llvm/unittests/ADT/APFloatTest.cpp | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/llvm/unittests/ADT/APFloatTest.cpp b/llvm/unittests/ADT/APFloatTest.cpp index f6af4b0..a105cd8 100644 --- a/llvm/unittests/ADT/APFloatTest.cpp +++ b/llvm/unittests/ADT/APFloatTest.cpp @@ -631,6 +631,54 @@ TEST(APFloatTest, Maximum) { EXPECT_TRUE(std::isnan(maximum(nan, f1).convertToDouble())); } +TEST(APFloatTest, MinimumNumber) { + APFloat f1(1.0); + APFloat f2(2.0); + APFloat zp(0.0); + APFloat zn(-0.0); + APFloat nan = APFloat::getNaN(APFloat::IEEEdouble()); + APFloat snan = APFloat::getSNaN(APFloat::IEEEdouble()); + + EXPECT_EQ(1.0, minimumnum(f1, f2).convertToDouble()); + EXPECT_EQ(1.0, minimumnum(f2, f1).convertToDouble()); + EXPECT_EQ(-0.0, minimumnum(zp, zn).convertToDouble()); + EXPECT_EQ(-0.0, minimumnum(zn, zp).convertToDouble()); + EXPECT_TRUE(minimumnum(zn, zp).isNegative()); + EXPECT_TRUE(minimumnum(zp, zn).isNegative()); + EXPECT_TRUE(minimumnum(zn, zn).isNegative()); + EXPECT_FALSE(minimumnum(zp, zp).isNegative()); + EXPECT_FALSE(std::isnan(minimumnum(f1, nan).convertToDouble())); + EXPECT_FALSE(std::isnan(minimumnum(nan, f1).convertToDouble())); + EXPECT_FALSE(std::isnan(minimumnum(f1, snan).convertToDouble())); + EXPECT_FALSE(std::isnan(minimumnum(snan, f1).convertToDouble())); + EXPECT_FALSE(minimumnum(snan, nan).isSignaling()); + EXPECT_FALSE(minimumnum(snan, snan).isSignaling()); +} + +TEST(APFloatTest, MaximumNumber) { + APFloat f1(1.0); + APFloat f2(2.0); + APFloat zp(0.0); + APFloat zn(-0.0); + APFloat nan = APFloat::getNaN(APFloat::IEEEdouble()); + APFloat snan = APFloat::getSNaN(APFloat::IEEEdouble()); + + EXPECT_EQ(2.0, maximumnum(f1, f2).convertToDouble()); + EXPECT_EQ(2.0, maximumnum(f2, f1).convertToDouble()); + EXPECT_EQ(0.0, maximumnum(zp, zn).convertToDouble()); + EXPECT_EQ(0.0, maximumnum(zn, zp).convertToDouble()); + EXPECT_FALSE(maximumnum(zn, zp).isNegative()); + EXPECT_FALSE(maximumnum(zp, zn).isNegative()); + EXPECT_TRUE(maximumnum(zn, zn).isNegative()); + EXPECT_FALSE(maximumnum(zp, zp).isNegative()); + EXPECT_FALSE(std::isnan(maximumnum(f1, nan).convertToDouble())); + EXPECT_FALSE(std::isnan(maximumnum(nan, f1).convertToDouble())); + EXPECT_FALSE(std::isnan(maximumnum(f1, snan).convertToDouble())); + EXPECT_FALSE(std::isnan(maximumnum(snan, f1).convertToDouble())); + EXPECT_FALSE(maximumnum(snan, nan).isSignaling()); + EXPECT_FALSE(maximumnum(snan, snan).isSignaling()); +} + TEST(APFloatTest, Denormal) { APFloat::roundingMode rdmd = APFloat::rmNearestTiesToEven; |