Index: llvm/include/llvm/Support/MathExtras.h =================================================================== --- llvm/include/llvm/Support/MathExtras.h +++ llvm/include/llvm/Support/MathExtras.h @@ -461,6 +461,16 @@ return N >= 64 || (minIntN(N) <= x && x <= maxIntN(N)); } +/// Checks if an unsigned integer is an N bit number shifted left by S. Dynamic +/// version of isShiftedUInt. +inline bool isShiftedUIntN(unsigned N, unsigned S, uint64_t x) { + assert( + N > 0 && + "isShiftedUIntN(0, S, x) doesn't make sense (refers to a 0-bit number)"); + assert(N + S <= 64 && "isShiftedUInt(N, S, x) with N + S > 64 is too wide."); + return isUIntN(N + S, x) && (x % (UINT64_C(1) << S) == 0); +} + /// Return true if the argument is a non-empty sequence of ones starting at the /// least significant bit with the remainder zero (32 bit version). /// Ex. isMask_32(0x0000FFFFU) == true. Index: llvm/unittests/Support/MathExtrasTest.cpp =================================================================== --- llvm/unittests/Support/MathExtrasTest.cpp +++ llvm/unittests/Support/MathExtrasTest.cpp @@ -493,6 +493,22 @@ EXPECT_FALSE((isShiftedUInt<10, 5>(uint64_t(0x201) << 6))); } +TEST(MathExtras, IsShiftedUIntN) { + EXPECT_TRUE((isShiftedUIntN(1, 0, 0))); + EXPECT_TRUE((isShiftedUIntN(1, 0, 1))); + EXPECT_FALSE((isShiftedUIntN(1, 0, 2))); + EXPECT_FALSE((isShiftedUIntN(1, 0, 3))); + EXPECT_FALSE((isShiftedUIntN(1, 0, 0x8000000000000000))); + EXPECT_TRUE((isShiftedUIntN(1, 63, 0x8000000000000000))); + EXPECT_TRUE((isShiftedUIntN(2, 62, 0xC000000000000000))); + EXPECT_FALSE((isShiftedUIntN(2, 62, 0xE000000000000000))); + + // 0x201 is ten bits long and has a 1 in the MSB and LSB. + EXPECT_TRUE((isShiftedUIntN(10, 5, (uint64_t(0x201) << 5)))); + EXPECT_FALSE((isShiftedUIntN(10, 5, (uint64_t(0x201) << 4)))); + EXPECT_FALSE((isShiftedUIntN(10, 5, (uint64_t(0x201) << 6)))); +} + TEST(MathExtras, IsShiftedInt) { EXPECT_TRUE((isShiftedInt<1, 0>(0))); EXPECT_TRUE((isShiftedInt<1, 0>(-1)));