Index: include/llvm/ADT/APInt.h =================================================================== --- include/llvm/ADT/APInt.h +++ include/llvm/ADT/APInt.h @@ -425,6 +425,36 @@ /// width without remainder. bool isSplat(unsigned SplatSizeInBits) const; + /// \returns true if the argument APInt value is a sequence of \param numBits + /// ones starting at the least significant bit with the remainder zero. + bool isMask(unsigned numBits) const { + assert(numBits != 0 && "numBits must be non-zero"); + assert(numBits <= BitWidth && "numBits out of range"); + if (isSingleWord()) + return VAL == (UINT64_MAX >> (APINT_BITS_PER_WORD - numBits)); + unsigned Ones = countTrailingOnes(); + return (numBits == Ones) && ((Ones + countLeadingZeros()) == BitWidth); + } + + /// \returns true if the argument is a non-empty sequence of ones starting at + /// the least significant bit with the remainder zero. + /// Ex. isMask(0x0000FFFFU) == true. + bool isMask() const { + if (isSingleWord()) + return isMask_64(VAL); + unsigned Ones = countTrailingOnes(); + return (Ones > 0) && ((Ones + countLeadingZeros()) == BitWidth); + } + + /// \brief Return true if the argument APInt value contains a sequence of ones + /// with the remainder zero. + bool isShiftedMask() const { + if (isSingleWord()) + return isShiftedMask_64(VAL); + unsigned Ones = countPopulation(); + return (Ones + countTrailingZeros() + countLeadingZeros()) == BitWidth; + } + /// @} /// \name Value Generators /// @{ @@ -1912,26 +1942,6 @@ return A.ugt(B) ? A : B; } -/// \returns true if the argument APInt value is a sequence of ones starting at -/// the least significant bit with the remainder zero. -inline bool isMask(unsigned numBits, const APInt &APIVal) { - return numBits <= APIVal.getBitWidth() && - 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(const APInt &APIVal) { - return (APIVal != 0) && isMask((APIVal - 1) | APIVal); -} - /// \brief Compute GCD of two APInt values. /// /// This function returns the greatest common divisor of the two APInt values Index: lib/Analysis/ScalarEvolution.cpp =================================================================== --- lib/Analysis/ScalarEvolution.cpp +++ lib/Analysis/ScalarEvolution.cpp @@ -5321,7 +5321,7 @@ // If C is a low-bits mask, the zero extend is serving to // mask off the high bits. Complement the operand and // re-apply the zext. - if (APIntOps::isMask(Z0TySize, CI->getValue())) + if (CI->getValue().isMask(Z0TySize)) return getZeroExtendExpr(getNotSCEV(Z0), UTy); // If C is a single bit, it may be in the sign-bit position Index: lib/CodeGen/CodeGenPrepare.cpp =================================================================== --- lib/CodeGen/CodeGenPrepare.cpp +++ lib/CodeGen/CodeGenPrepare.cpp @@ -4905,7 +4905,7 @@ // // Also avoid hoisting if we didn't see any ands with the exact DemandBits // mask, since these are the only ands that will be removed by isel. - if (ActiveBits <= 1 || !APIntOps::isMask(ActiveBits, DemandBits) || + if (ActiveBits <= 1 || !DemandBits.isMask(ActiveBits) || WidestAndBits != DemandBits) return false; Index: lib/CodeGen/SelectionDAG/DAGCombiner.cpp =================================================================== --- lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -3337,7 +3337,7 @@ unsigned MaskBits = AndMask.countTrailingOnes(); EVT HalfVT = EVT::getIntegerVT(*DAG.getContext(), Size / 2); - if (APIntOps::isMask(AndMask) && + if (AndMask.isMask() && // Required bits must not span the two halves of the integer and // must fit in the half size type. (ShiftBits + MaskBits <= Size / 2) && @@ -3377,7 +3377,7 @@ bool &NarrowLoad) { uint32_t ActiveBits = AndC->getAPIntValue().getActiveBits(); - if (ActiveBits == 0 || !APIntOps::isMask(ActiveBits, AndC->getAPIntValue())) + if (ActiveBits == 0 || !AndC->getAPIntValue().isMask(ActiveBits)) return false; ExtVT = EVT::getIntegerVT(*DAG.getContext(), ActiveBits); Index: lib/Target/Hexagon/HexagonGenExtract.cpp =================================================================== --- lib/Target/Hexagon/HexagonGenExtract.cpp +++ lib/Target/Hexagon/HexagonGenExtract.cpp @@ -197,13 +197,13 @@ // It is still ok to generate extract, but only if the mask eliminates // those bits (i.e. M does not have any bits set beyond U). APInt C = APInt::getHighBitsSet(BW, BW-U); - if (M.intersects(C) || !APIntOps::isMask(W, M)) + if (M.intersects(C) || !M.isMask(W)) return false; } else { // Check if M starts with a contiguous sequence of W times 1 bits. Get // the low U bits of M (which eliminates the 0 bits shifted in on the // left), and check if the result is APInt's "mask": - if (!APIntOps::isMask(W, M.getLoBits(U))) + if (!M.getLoBits(U).isMask(W)) return false; } Index: lib/Target/X86/X86ISelLowering.cpp =================================================================== --- lib/Target/X86/X86ISelLowering.cpp +++ lib/Target/X86/X86ISelLowering.cpp @@ -31519,7 +31519,7 @@ APInt SplatVal; if (!ISD::isConstantSplatVector(Op1.getNode(), SplatVal) || - !APIntOps::isMask(SplatVal)) + !SplatVal.isMask()) return SDValue(); if (!SupportedVectorShiftWithImm(VT0.getSimpleVT(), Subtarget, ISD::SRL)) @@ -32114,7 +32114,7 @@ if (ISD::isConstantSplatVector(In.getOperand(1).getNode(), C)) { // C should be equal to UINT32_MAX / UINT16_MAX / UINT8_MAX according // the element size of the destination type. - return APIntOps::isMask(VT.getScalarSizeInBits(), C) ? In.getOperand(0) : + return C.isMask(VT.getScalarSizeInBits()) ? In.getOperand(0) : SDValue(); } return SDValue(); Index: lib/Transforms/InstCombine/InstCombineAndOrXor.cpp =================================================================== --- lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -309,7 +309,7 @@ static bool isRunOfOnes(ConstantInt *Val, uint32_t &MB, uint32_t &ME) { const APInt& V = Val->getValue(); uint32_t BitWidth = Val->getType()->getBitWidth(); - if (!APIntOps::isShiftedMask(V)) return false; + if (!V.isShiftedMask()) return false; // look for the first zero bit after the run of ones MB = BitWidth - ((V - 1) ^ V).countLeadingZeros(); Index: lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp =================================================================== --- lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp +++ lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp @@ -1558,7 +1558,7 @@ break; case Intrinsic::amdgcn_buffer_load: case Intrinsic::amdgcn_buffer_load_format: { - if (VWidth == 1 || !APIntOps::isMask(DemandedElts)) + if (VWidth == 1 || !DemandedElts.isMask()) return nullptr; // TODO: Handle 3 vectors when supported in code gen. Index: unittests/ADT/APIntTest.cpp =================================================================== --- unittests/ADT/APIntTest.cpp +++ unittests/ADT/APIntTest.cpp @@ -1559,43 +1559,44 @@ } 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))); + EXPECT_FALSE(APInt(32, 0x01010101).isMask()); + EXPECT_FALSE(APInt(32, 0xf0000000).isMask()); + EXPECT_FALSE(APInt(32, 0xffff0000).isMask()); + EXPECT_FALSE(APInt(32, 0xff << 1).isMask()); for (int N : { 1, 2, 3, 4, 7, 8, 16, 32, 64, 127, 128, 129, 256 }) { - EXPECT_FALSE(APIntOps::isMask(APInt(N, 0))); + EXPECT_FALSE(APInt(N, 0).isMask()); APInt One(N, 1); for (int I = 1; I <= N; ++I) { APInt MaskVal = One.shl(I) - 1; - EXPECT_TRUE(APIntOps::isMask(MaskVal)); + EXPECT_TRUE(MaskVal.isMask()); + EXPECT_TRUE(MaskVal.isMask(I)); } } } TEST(APIntTest, isShiftedMask) { - EXPECT_FALSE(APIntOps::isShiftedMask(APInt(32, 0x01010101))); - EXPECT_TRUE(APIntOps::isShiftedMask(APInt(32, 0xf0000000))); - EXPECT_TRUE(APIntOps::isShiftedMask(APInt(32, 0xffff0000))); - EXPECT_TRUE(APIntOps::isShiftedMask(APInt(32, 0xff << 1))); + EXPECT_FALSE(APInt(32, 0x01010101).isShiftedMask()); + EXPECT_TRUE(APInt(32, 0xf0000000).isShiftedMask()); + EXPECT_TRUE(APInt(32, 0xffff0000).isShiftedMask()); + EXPECT_TRUE(APInt(32, 0xff << 1).isShiftedMask()); for (int N : { 1, 2, 3, 4, 7, 8, 16, 32, 64, 127, 128, 129, 256 }) { - EXPECT_FALSE(APIntOps::isShiftedMask(APInt(N, 0))); + EXPECT_FALSE(APInt(N, 0).isShiftedMask()); APInt One(N, 1); for (int I = 1; I < N; ++I) { APInt MaskVal = One.shl(I) - 1; - EXPECT_TRUE(APIntOps::isShiftedMask(MaskVal)); + EXPECT_TRUE(MaskVal.isShiftedMask()); } for (int I = 1; I < N - 1; ++I) { APInt MaskVal = One.shl(I); - EXPECT_TRUE(APIntOps::isShiftedMask(MaskVal)); + EXPECT_TRUE(MaskVal.isShiftedMask()); } for (int I = 1; I < N; ++I) { APInt MaskVal = APInt::getHighBitsSet(N, I); - EXPECT_TRUE(APIntOps::isShiftedMask(MaskVal)); + EXPECT_TRUE(MaskVal.isShiftedMask()); } } }