diff options
Diffstat (limited to 'llvm')
| -rw-r--r-- | llvm/include/llvm/ADT/APInt.h | 7 | ||||
| -rw-r--r-- | llvm/unittests/ADT/APIntTest.cpp | 17 |
2 files changed, 24 insertions, 0 deletions
diff --git a/llvm/include/llvm/ADT/APInt.h b/llvm/include/llvm/ADT/APInt.h index 1e10253ffe1..ff32e3aa3cd 100644 --- a/llvm/include/llvm/ADT/APInt.h +++ b/llvm/include/llvm/ADT/APInt.h @@ -1782,6 +1782,13 @@ inline bool isMask(unsigned numBits, const APInt &APIVal) { APIVal == APInt::getLowBitsSet(APIVal.getBitWidth(), numBits); } +/// \returns 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(0x0000FFFFU) == true. +inline bool isMask(const APInt &Value) { + return (Value != 0) && ((Value + 1) & Value) == 0; +} + /// \brief Return true if the argument APInt value contains a sequence of ones /// with the remainder zero. inline bool isShiftedMask(unsigned numBits, const APInt &APIVal) { diff --git a/llvm/unittests/ADT/APIntTest.cpp b/llvm/unittests/ADT/APIntTest.cpp index c59e695b04e..4ae70251d4e 100644 --- a/llvm/unittests/ADT/APIntTest.cpp +++ b/llvm/unittests/ADT/APIntTest.cpp @@ -994,6 +994,23 @@ TEST(APIntTest, IsSplat) { EXPECT_TRUE(E.isSplat(32)); } +TEST(APIntTest, isMask) { + EXPECT_FALSE(APIntOps::isMask(APInt(32, 0x01010101))); + EXPECT_FALSE(APIntOps::isMask(APInt(32, 0xf0000000))); + EXPECT_FALSE(APIntOps::isMask(APInt(32, 0xffff0000))); + EXPECT_FALSE(APIntOps::isMask(APInt(32, 0xff << 1))); + + for (int N : { 1, 2, 3, 4, 7, 8, 16, 32, 64, 127, 128, 129, 256 }) { + EXPECT_FALSE(APIntOps::isMask(APInt(N, 0))); + + APInt One(N, 1); + for (int I = 1; I <= N; ++I) { + APInt MaskVal = One.shl(I) - 1; + EXPECT_TRUE(APIntOps::isMask(MaskVal)); + } + } +} + #if defined(__clang__) // Disable the pragma warning from versions of Clang without -Wself-move #pragma clang diagnostic push |

