diff options
author | Tim Shen <timshen91@gmail.com> | 2017-01-23 22:39:35 +0000 |
---|---|---|
committer | Tim Shen <timshen91@gmail.com> | 2017-01-23 22:39:35 +0000 |
commit | fd1e5aa8dffa8b26e59fb340668b264b9ac80382 (patch) | |
tree | 61c9f22bd15cd3ebb3f84e6d1889cbc21a09af5d /llvm/unittests/ADT/APFloatTest.cpp | |
parent | 09cca093a390725df66af1a45ef0eb4aa695b5e5 (diff) | |
download | bcm5719-llvm-fd1e5aa8dffa8b26e59fb340668b264b9ac80382.tar.gz bcm5719-llvm-fd1e5aa8dffa8b26e59fb340668b264b9ac80382.zip |
[APFloat] Switch from (PPCDoubleDoubleImpl, IEEEdouble) layout to (IEEEdouble, IEEEdouble)
Summary:
This patch changes the layout of DoubleAPFloat, and adjust all
operations to do either:
1) (IEEEdouble, IEEEdouble) -> (uint64_t, uint64_t) -> PPCDoubleDoubleImpl,
then run the old algorithm.
2) Do the right thing directly.
1) includes multiply, divide, remainder, mod, fusedMultiplyAdd, roundToIntegral,
convertFromString, next, convertToInteger, convertFromAPInt,
convertFromSignExtendedInteger, convertFromZeroExtendedInteger,
convertToHexString, toString, getExactInverse.
2) includes makeZero, makeLargest, makeSmallest, makeSmallestNormalized,
compare, bitwiseIsEqual, bitcastToAPInt, isDenormal, isSmallest,
isLargest, isInteger, ilogb, scalbn, frexp, hash_value, Profile.
I could split this into two patches, e.g. use
1) for all operatoins first, then incrementally change some of them to
2). I didn't do that, because 1) involves code that converts data between
PPCDoubleDoubleImpl and (IEEEdouble, IEEEdouble) back and forth, and may
pessimize the compiler. Instead, I find easy functions and use
approach 2) for them directly.
Next step is to implement move multiply and divide from 1) to 2). I don't
have plans for other functions in 1).
Differential Revision: https://reviews.llvm.org/D27872
llvm-svn: 292839
Diffstat (limited to 'llvm/unittests/ADT/APFloatTest.cpp')
-rw-r--r-- | llvm/unittests/ADT/APFloatTest.cpp | 131 |
1 files changed, 114 insertions, 17 deletions
diff --git a/llvm/unittests/ADT/APFloatTest.cpp b/llvm/unittests/ADT/APFloatTest.cpp index 83fb213109a..6e709cd3cc5 100644 --- a/llvm/unittests/ADT/APFloatTest.cpp +++ b/llvm/unittests/ADT/APFloatTest.cpp @@ -9,6 +9,7 @@ #include "llvm/ADT/APFloat.h" #include "llvm/ADT/APSInt.h" +#include "llvm/ADT/Hashing.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/FormatVariadic.h" #include "llvm/Support/raw_ostream.h" @@ -3181,7 +3182,7 @@ TEST(APFloatTest, PPCDoubleDoubleAddSpecial) { 0x7948000000000000ull, 0ull, APFloat::fcInfinity, APFloat::rmNearestTiesToEven), // TODO: change the 4th 0x75effffffffffffe to 0x75efffffffffffff when - // PPCDoubleDoubleImpl is gone. + // semPPCDoubleDoubleLegacy is gone. // LDBL_MAX + (1.011111... >> (1023 - 106) + (1.1111111...0 >> (1023 - // 160))) = fcNormal std::make_tuple(0x7fefffffffffffffull, 0x7c8ffffffffffffeull, @@ -3234,14 +3235,14 @@ TEST(APFloatTest, PPCDoubleDoubleAdd) { 0x3ff0000000000000ull, 0x0000000000000001ull, APFloat::rmNearestTiesToEven), // TODO: change 0xf950000000000000 to 0xf940000000000000, when - // PPCDoubleDoubleImpl is gone. + // semPPCDoubleDoubleLegacy is gone. // (DBL_MAX - 1 << (1023 - 105)) + (1 << (1023 - 53) + 0) = DBL_MAX + // 1.11111... << (1023 - 52) std::make_tuple(0x7fefffffffffffffull, 0xf950000000000000ull, 0x7c90000000000000ull, 0, 0x7fefffffffffffffull, 0x7c8ffffffffffffeull, APFloat::rmNearestTiesToEven), // TODO: change 0xf950000000000000 to 0xf940000000000000, when - // PPCDoubleDoubleImpl is gone. + // semPPCDoubleDoubleLegacy is gone. // (1 << (1023 - 53) + 0) + (DBL_MAX - 1 << (1023 - 105)) = DBL_MAX + // 1.11111... << (1023 - 52) std::make_tuple(0x7c90000000000000ull, 0, 0x7fefffffffffffffull, @@ -3262,7 +3263,7 @@ TEST(APFloatTest, PPCDoubleDoubleAdd) { << formatv("({0:x} + {1:x}) + ({2:x} + {3:x})", Op1[0], Op1[1], Op2[0], Op2[1]) .str(); - EXPECT_EQ(Expected[1], A1.getSecondFloat().bitcastToAPInt().getRawData()[0]) + EXPECT_EQ(Expected[1], A1.bitcastToAPInt().getRawData()[1]) << formatv("({0:x} + {1:x}) + ({2:x} + {3:x})", Op1[0], Op1[1], Op2[0], Op2[1]) .str(); @@ -3296,7 +3297,7 @@ TEST(APFloatTest, PPCDoubleDoubleSubtract) { << formatv("({0:x} + {1:x}) - ({2:x} + {3:x})", Op1[0], Op1[1], Op2[0], Op2[1]) .str(); - EXPECT_EQ(Expected[1], A1.getSecondFloat().bitcastToAPInt().getRawData()[0]) + EXPECT_EQ(Expected[1], A1.bitcastToAPInt().getRawData()[1]) << formatv("({0:x} + {1:x}) - ({2:x} + {3:x})", Op1[0], Op1[1], Op2[0], Op2[1]) .str(); @@ -3496,12 +3497,53 @@ TEST(APFloatTest, PPCDoubleDoubleCompare) { APFloat A1(APFloat::PPCDoubleDouble(), APInt(128, 2, Op1)); APFloat A2(APFloat::PPCDoubleDouble(), APInt(128, 2, Op2)); EXPECT_EQ(Expected, A1.compare(A2)) - << formatv("({0:x} + {1:x}) - ({2:x} + {3:x})", Op1[0], Op1[1], Op2[0], + << formatv("compare(({0:x} + {1:x}), ({2:x} + {3:x}))", Op1[0], Op1[1], + Op2[0], Op2[1]) + .str(); + } +} + +TEST(APFloatTest, PPCDoubleDoubleBitwiseIsEqual) { + using DataType = std::tuple<uint64_t, uint64_t, uint64_t, uint64_t, bool>; + + DataType Data[] = { + // (1 + 0) = (1 + 0) + std::make_tuple(0x3ff0000000000000ull, 0, 0x3ff0000000000000ull, 0, true), + // (1 + 0) != (1.00...1 + 0) + std::make_tuple(0x3ff0000000000000ull, 0, 0x3ff0000000000001ull, 0, + false), + // NaN = NaN + std::make_tuple(0x7ff8000000000000ull, 0, 0x7ff8000000000000ull, 0, true), + // NaN != NaN with a different bit pattern + std::make_tuple(0x7ff8000000000000ull, 0, 0x7ff8000000000000ull, + 0x3ff0000000000000ull, false), + // Inf = Inf + std::make_tuple(0x7ff0000000000000ull, 0, 0x7ff0000000000000ull, 0, true), + }; + + for (auto Tp : Data) { + uint64_t Op1[2], Op2[2]; + bool Expected; + std::tie(Op1[0], Op1[1], Op2[0], Op2[1], Expected) = Tp; + + APFloat A1(APFloat::PPCDoubleDouble(), APInt(128, 2, Op1)); + APFloat A2(APFloat::PPCDoubleDouble(), APInt(128, 2, Op2)); + EXPECT_EQ(Expected, A1.bitwiseIsEqual(A2)) + << formatv("({0:x} + {1:x}) = ({2:x} + {3:x})", Op1[0], Op1[1], Op2[0], Op2[1]) .str(); } } +TEST(APFloatTest, PPCDoubleDoubleHashValue) { + uint64_t Data1[] = {0x3ff0000000000001ull, 0x0000000000000001ull}; + uint64_t Data2[] = {0x3ff0000000000001ull, 0}; + // The hash values are *hopefully* different. + EXPECT_NE( + hash_value(APFloat(APFloat::PPCDoubleDouble(), APInt(128, 2, Data1))), + hash_value(APFloat(APFloat::PPCDoubleDouble(), APInt(128, 2, Data2)))); +} + TEST(APFloatTest, PPCDoubleDoubleChangeSign) { uint64_t Data[] = { 0x400f000000000000ull, 0xbcb0000000000000ull, @@ -3531,6 +3573,13 @@ TEST(APFloatTest, PPCDoubleDoubleFactories) { } { uint64_t Data[] = { + 0x7fefffffffffffffull, 0x7c8ffffffffffffeull, + }; + EXPECT_EQ(APInt(128, 2, Data), + APFloat::getLargest(APFloat::PPCDoubleDouble()).bitcastToAPInt()); + } + { + uint64_t Data[] = { 0x0000000000000001ull, 0, }; EXPECT_EQ( @@ -3553,24 +3602,72 @@ TEST(APFloatTest, PPCDoubleDoubleFactories) { } { uint64_t Data[] = { + 0xffefffffffffffffull, 0xfc8ffffffffffffeull, + }; + EXPECT_EQ( + APInt(128, 2, Data), + APFloat::getLargest(APFloat::PPCDoubleDouble(), true).bitcastToAPInt()); + } + { + uint64_t Data[] = { 0x8000000000000001ull, 0x0000000000000000ull, }; EXPECT_EQ(APInt(128, 2, Data), APFloat::getSmallest(APFloat::PPCDoubleDouble(), true) .bitcastToAPInt()); } - - EXPECT_EQ(0x8360000000000000ull, - APFloat::getSmallestNormalized(APFloat::PPCDoubleDouble(), true) - .bitcastToAPInt() - .getRawData()[0]); - EXPECT_EQ(0x0000000000000000ull, - APFloat::getSmallestNormalized(APFloat::PPCDoubleDouble(), true) - .getSecondFloat() - .bitcastToAPInt() - .getRawData()[0]); - + { + uint64_t Data[] = { + 0x8360000000000000ull, 0x0000000000000000ull, + }; + EXPECT_EQ(APInt(128, 2, Data), + APFloat::getSmallestNormalized(APFloat::PPCDoubleDouble(), true) + .bitcastToAPInt()); + } EXPECT_TRUE(APFloat::getSmallest(APFloat::PPCDoubleDouble()).isSmallest()); EXPECT_TRUE(APFloat::getLargest(APFloat::PPCDoubleDouble()).isLargest()); } + +TEST(APFloatTest, PPCDoubleDoubleIsDenormal) { + EXPECT_TRUE(APFloat::getSmallest(APFloat::PPCDoubleDouble()).isDenormal()); + EXPECT_FALSE(APFloat::getLargest(APFloat::PPCDoubleDouble()).isDenormal()); + EXPECT_FALSE( + APFloat::getSmallestNormalized(APFloat::PPCDoubleDouble()).isDenormal()); + { + // (4 + 3) is not normalized + uint64_t Data[] = { + 0x4010000000000000ull, 0x4008000000000000ull, + }; + EXPECT_TRUE( + APFloat(APFloat::PPCDoubleDouble(), APInt(128, 2, Data)).isDenormal()); + } +} + +TEST(APFloatTest, PPCDoubleDoubleScalbn) { + // 3.0 + 3.0 << 53 + uint64_t Input[] = { + 0x4008000000000000ull, 0x3cb8000000000000ull, + }; + APFloat Result = + scalbn(APFloat(APFloat::PPCDoubleDouble(), APInt(128, 2, Input)), 1, + APFloat::rmNearestTiesToEven); + // 6.0 + 6.0 << 53 + EXPECT_EQ(0x4018000000000000ull, Result.bitcastToAPInt().getRawData()[0]); + EXPECT_EQ(0x3cc8000000000000ull, Result.bitcastToAPInt().getRawData()[1]); +} + +TEST(APFloatTest, PPCDoubleDoubleFrexp) { + // 3.0 + 3.0 << 53 + uint64_t Input[] = { + 0x4008000000000000ull, 0x3cb8000000000000ull, + }; + int Exp; + // 0.75 + 0.75 << 53 + APFloat Result = + frexp(APFloat(APFloat::PPCDoubleDouble(), APInt(128, 2, Input)), Exp, + APFloat::rmNearestTiesToEven); + EXPECT_EQ(2, Exp); + EXPECT_EQ(0x3fe8000000000000ull, Result.bitcastToAPInt().getRawData()[0]); + EXPECT_EQ(0x3c98000000000000ull, Result.bitcastToAPInt().getRawData()[1]); +} } |