diff options
| -rw-r--r-- | llvm/include/llvm/Support/MathExtras.h | 18 | ||||
| -rw-r--r-- | llvm/unittests/Support/MathExtrasTest.cpp | 38 |
2 files changed, 52 insertions, 4 deletions
diff --git a/llvm/include/llvm/Support/MathExtras.h b/llvm/include/llvm/Support/MathExtras.h index e9930f68d7c..0c95ce55d81 100644 --- a/llvm/include/llvm/Support/MathExtras.h +++ b/llvm/include/llvm/Support/MathExtras.h @@ -283,14 +283,19 @@ inline bool isInt<32>(int64_t x) { /// left by S. template<unsigned N, unsigned S> inline bool isShiftedInt(int64_t x) { - return isInt<N+S>(x) && (x % (1<<S) == 0); + static_assert( + N > 0, "isShiftedInt<0> doesn't make sense (refers to a 0-bit number."); + static_assert(N + S <= 64, "isShiftedInt<N, S> with N + S > 64 is too wide."); + return isInt<N + S>(x) && (x % (UINT64_C(1) << S) == 0); } /// isUInt - Checks if an unsigned integer fits into the given bit width. template<unsigned N> inline bool isUInt(uint64_t x) { + static_assert(N > 0, "isUInt<0> doesn't make sense."); return N >= 64 || x < (UINT64_C(1)<<(N)); } + // Template specializations to get better code for common cases. template<> inline bool isUInt<8>(uint64_t x) { @@ -305,11 +310,16 @@ inline bool isUInt<32>(uint64_t x) { return static_cast<uint32_t>(x) == x; } -/// isShiftedUInt<N,S> - Checks if a unsigned integer is an N bit number shifted -/// left by S. +/// Checks if a unsigned integer is an N bit number shifted left by S. template<unsigned N, unsigned S> inline bool isShiftedUInt(uint64_t x) { - return isUInt<N+S>(x) && (x % (1<<S) == 0); + static_assert( + N > 0, "isShiftedUInt<0> doesn't make sense (refers to a 0-bit number)"); + static_assert(N + S <= 64, + "isShiftedUInt<N, S> with N + S > 64 is too wide."); + // Per the two static_asserts above, S must be strictly less than 64. So + // 1 << S is not undefined behavior. + return isUInt<N + S>(x) && (x % (UINT64_C(1) << S) == 0); } /// Gets the maximum value for a N-bit unsigned integer. diff --git a/llvm/unittests/Support/MathExtrasTest.cpp b/llvm/unittests/Support/MathExtrasTest.cpp index ef46311665d..3d449ccb209 100644 --- a/llvm/unittests/Support/MathExtrasTest.cpp +++ b/llvm/unittests/Support/MathExtrasTest.cpp @@ -388,4 +388,42 @@ TEST(MathExtras, SaturatingMultiplyAdd) { SaturatingMultiplyAddTestHelper<uint64_t>(); } +TEST(MathExtras, IsShiftedUInt) { + EXPECT_TRUE((isShiftedUInt<1, 0>(0))); + EXPECT_TRUE((isShiftedUInt<1, 0>(1))); + EXPECT_FALSE((isShiftedUInt<1, 0>(2))); + EXPECT_FALSE((isShiftedUInt<1, 0>(3))); + EXPECT_FALSE((isShiftedUInt<1, 0>(0x8000000000000000))); + EXPECT_TRUE((isShiftedUInt<1, 63>(0x8000000000000000))); + EXPECT_TRUE((isShiftedUInt<2, 62>(0xC000000000000000))); + EXPECT_FALSE((isShiftedUInt<2, 62>(0xE000000000000000))); + + // 0x201 is ten bits long and has a 1 in the MSB and LSB. + EXPECT_TRUE((isShiftedUInt<10, 5>(uint64_t(0x201) << 5))); + EXPECT_FALSE((isShiftedUInt<10, 5>(uint64_t(0x201) << 4))); + EXPECT_FALSE((isShiftedUInt<10, 5>(uint64_t(0x201) << 6))); } + +TEST(MathExtras, IsShiftedInt) { + EXPECT_TRUE((isShiftedInt<1, 0>(0))); + EXPECT_TRUE((isShiftedInt<1, 0>(-1))); + EXPECT_FALSE((isShiftedInt<1, 0>(2))); + EXPECT_FALSE((isShiftedInt<1, 0>(3))); + EXPECT_FALSE((isShiftedInt<1, 0>(0x8000000000000000))); + EXPECT_TRUE((isShiftedInt<1, 63>(0x8000000000000000))); + EXPECT_TRUE((isShiftedInt<2, 62>(0xC000000000000000))); + EXPECT_FALSE((isShiftedInt<2, 62>(0xE000000000000000))); + + // 0x201 is ten bits long and has a 1 in the MSB and LSB. + EXPECT_TRUE((isShiftedInt<11, 5>(int64_t(0x201) << 5))); + EXPECT_FALSE((isShiftedInt<11, 5>(int64_t(0x201) << 3))); + EXPECT_FALSE((isShiftedInt<11, 5>(int64_t(0x201) << 6))); + EXPECT_TRUE((isShiftedInt<11, 5>(-(int64_t(0x201) << 5)))); + EXPECT_FALSE((isShiftedInt<11, 5>(-(int64_t(0x201) << 3)))); + EXPECT_FALSE((isShiftedInt<11, 5>(-(int64_t(0x201) << 6)))); + + EXPECT_TRUE((isShiftedInt<6, 10>(-(int64_t(1) << 15)))); + EXPECT_FALSE((isShiftedInt<6, 10>(int64_t(1) << 15))); +} + +} // namespace |

