[llvm] a024d35 - [APInt.h] Clean up the APInt interface. NFC.

Geoffrey Martin-Noble via llvm-commits llvm-commits at lists.llvm.org
Wed Sep 8 16:43:55 PDT 2021


Thanks for the prompt fix! :-)

On Wed, Sep 8, 2021 at 4:35 PM Chris Lattner <clattner at nondot.org> wrote:

> Fixed in rG717ed1c31052, sorry for the breakage!
>
> -Chris
>
> On Sep 8, 2021, at 4:32 PM, Geoffrey Martin-Noble <gcmn at google.com> wrote:
>
> I'm seeing failures from this because clang uses APInt::needsCleanup in
> Expr.cpp which was public before
>
> ```
> llvm-project/clang/lib/AST/Expr.cpp:260:25: error: 'needsCleanup' is a
> private member of 'llvm::APInt'
>     if (!Value.getInt().needsCleanup())
>                         ^
> llvm-project/llvm/include/llvm/ADT/APInt.h:1994:8: note: declared private
> here
>   bool needsCleanup() const { return !isSingleWord(); }
> ```
>
> On Wed, Sep 8, 2021 at 4:09 PM Chris Lattner via llvm-commits <
> llvm-commits at lists.llvm.org> wrote:
>
>>
>> Author: Chris Lattner
>> Date: 2021-09-08T16:08:57-07:00
>> New Revision: a024d35b3885490221e78b835b087a830cc3c325
>>
>> URL:
>> https://github.com/llvm/llvm-project/commit/a024d35b3885490221e78b835b087a830cc3c325
>> DIFF:
>> https://github.com/llvm/llvm-project/commit/a024d35b3885490221e78b835b087a830cc3c325.diff
>>
>> LOG: [APInt.h] Clean up the APInt interface. NFC.
>>
>> This moves all the private implementation details to the bottom of
>> the header, and pushes all the "make an APInt" stuff up to the top.
>> This is in prep for making other changes to spiff up APInt a bit.
>>
>> Added:
>>
>>
>> Modified:
>>     llvm/include/llvm/ADT/APInt.h
>>
>> Removed:
>>
>>
>>
>>
>> ################################################################################
>> diff  --git a/llvm/include/llvm/ADT/APInt.h
>> b/llvm/include/llvm/ADT/APInt.h
>> index 68a229478c189..7ab49d23840a1 100644
>> --- a/llvm/include/llvm/ADT/APInt.h
>> +++ b/llvm/include/llvm/ADT/APInt.h
>> @@ -87,176 +87,6 @@ class LLVM_NODISCARD APInt {
>>
>>    static constexpr WordType WORDTYPE_MAX = ~WordType(0);
>>
>> -private:
>> -  /// This union is used to store the integer value. When the
>> -  /// integer bit-width <= 64, it uses VAL, otherwise it uses pVal.
>> -  union {
>> -    uint64_t VAL;   ///< Used to store the <= 64 bits integer value.
>> -    uint64_t *pVal; ///< Used to store the >64 bits integer value.
>> -  } U;
>> -
>> -  unsigned BitWidth; ///< The number of bits in this APInt.
>> -
>> -  friend struct DenseMapInfo<APInt>;
>> -
>> -  friend class APSInt;
>> -
>> -  /// Fast internal constructor
>> -  ///
>> -  /// This constructor is used only internally for speed of construction
>> of
>> -  /// temporaries. It is unsafe for general use so it is not public.
>> -  APInt(uint64_t *val, unsigned bits) : BitWidth(bits) {
>> -    U.pVal = val;
>> -  }
>> -
>> -  /// Determine which word a bit is in.
>> -  ///
>> -  /// \returns the word position for the specified bit position.
>> -  static unsigned whichWord(unsigned bitPosition) {
>> -    return bitPosition / APINT_BITS_PER_WORD;
>> -  }
>> -
>> -  /// Determine which bit in a word a bit is in.
>> -  ///
>> -  /// \returns the bit position in a word for the specified bit position
>> -  /// in the APInt.
>> -  static unsigned whichBit(unsigned bitPosition) {
>> -    return bitPosition % APINT_BITS_PER_WORD;
>> -  }
>> -
>> -  /// Get a single bit mask.
>> -  ///
>> -  /// \returns a uint64_t with only bit at "whichBit(bitPosition)" set
>> -  /// This method generates and returns a uint64_t (word) mask for a
>> single
>> -  /// bit at a specific bit position. This is used to mask the bit in the
>> -  /// corresponding word.
>> -  static uint64_t maskBit(unsigned bitPosition) {
>> -    return 1ULL << whichBit(bitPosition);
>> -  }
>> -
>> -  /// Clear unused high order bits
>> -  ///
>> -  /// This method is used internally to clear the top "N" bits in the
>> high order
>> -  /// word that are not used by the APInt. This is needed after the most
>> -  /// significant word is assigned a value to ensure that those bits are
>> -  /// zero'd out.
>> -  APInt &clearUnusedBits() {
>> -    // Compute how many bits are used in the final word
>> -    unsigned WordBits = ((BitWidth-1) % APINT_BITS_PER_WORD) + 1;
>> -
>> -    // Mask out the high bits.
>> -    uint64_t mask = WORDTYPE_MAX >> (APINT_BITS_PER_WORD - WordBits);
>> -    if (isSingleWord())
>> -      U.VAL &= mask;
>> -    else
>> -      U.pVal[getNumWords() - 1] &= mask;
>> -    return *this;
>> -  }
>> -
>> -  /// Get the word corresponding to a bit position
>> -  /// \returns the corresponding word for the specified bit position.
>> -  uint64_t getWord(unsigned bitPosition) const {
>> -    return isSingleWord() ? U.VAL : U.pVal[whichWord(bitPosition)];
>> -  }
>> -
>> -  /// Utility method to change the bit width of this APInt to new bit
>> width,
>> -  /// allocating and/or deallocating as necessary. There is no guarantee
>> on the
>> -  /// value of any bits upon return. Caller should populate the bits
>> after.
>> -  void reallocate(unsigned NewBitWidth);
>> -
>> -  /// Convert a char array into an APInt
>> -  ///
>> -  /// \param radix 2, 8, 10, 16, or 36
>> -  /// Converts a string into a number.  The string must be non-empty
>> -  /// and well-formed as a number of the given base. The bit-width
>> -  /// must be sufficient to hold the result.
>> -  ///
>> -  /// This is used by the constructors that take string arguments.
>> -  ///
>> -  /// StringRef::getAsInteger is superficially similar but (1) does
>> -  /// not assume that the string is well-formed and (2) grows the
>> -  /// result to hold the input.
>> -  void fromString(unsigned numBits, StringRef str, uint8_t radix);
>> -
>> -  /// An internal division function for dividing APInts.
>> -  ///
>> -  /// This is used by the toString method to divide by the radix. It
>> simply
>> -  /// provides a more convenient form of divide for internal use since
>> KnuthDiv
>> -  /// has specific constraints on its inputs. If those constraints are
>> not met
>> -  /// then it provides a simpler form of divide.
>> -  static void divide(const WordType *LHS, unsigned lhsWords,
>> -                     const WordType *RHS, unsigned rhsWords, WordType
>> *Quotient,
>> -                     WordType *Remainder);
>> -
>> -  /// out-of-line slow case for inline constructor
>> -  void initSlowCase(uint64_t val, bool isSigned);
>> -
>> -  /// shared code between two array constructors
>> -  void initFromArray(ArrayRef<uint64_t> array);
>> -
>> -  /// out-of-line slow case for inline copy constructor
>> -  void initSlowCase(const APInt &that);
>> -
>> -  /// out-of-line slow case for shl
>> -  void shlSlowCase(unsigned ShiftAmt);
>> -
>> -  /// out-of-line slow case for lshr.
>> -  void lshrSlowCase(unsigned ShiftAmt);
>> -
>> -  /// out-of-line slow case for ashr.
>> -  void ashrSlowCase(unsigned ShiftAmt);
>> -
>> -  /// out-of-line slow case for operator=
>> -  void AssignSlowCase(const APInt &RHS);
>> -
>> -  /// out-of-line slow case for operator==
>> -  bool EqualSlowCase(const APInt &RHS) const LLVM_READONLY;
>> -
>> -  /// out-of-line slow case for countLeadingZeros
>> -  unsigned countLeadingZerosSlowCase() const LLVM_READONLY;
>> -
>> -  /// out-of-line slow case for countLeadingOnes.
>> -  unsigned countLeadingOnesSlowCase() const LLVM_READONLY;
>> -
>> -  /// out-of-line slow case for countTrailingZeros.
>> -  unsigned countTrailingZerosSlowCase() const LLVM_READONLY;
>> -
>> -  /// out-of-line slow case for countTrailingOnes
>> -  unsigned countTrailingOnesSlowCase() const LLVM_READONLY;
>> -
>> -  /// out-of-line slow case for countPopulation
>> -  unsigned countPopulationSlowCase() const LLVM_READONLY;
>> -
>> -  /// out-of-line slow case for intersects.
>> -  bool intersectsSlowCase(const APInt &RHS) const LLVM_READONLY;
>> -
>> -  /// out-of-line slow case for isSubsetOf.
>> -  bool isSubsetOfSlowCase(const APInt &RHS) const LLVM_READONLY;
>> -
>> -  /// out-of-line slow case for setBits.
>> -  void setBitsSlowCase(unsigned loBit, unsigned hiBit);
>> -
>> -  /// out-of-line slow case for flipAllBits.
>> -  void flipAllBitsSlowCase();
>> -
>> -  /// out-of-line slow case for operator&=.
>> -  void AndAssignSlowCase(const APInt& RHS);
>> -
>> -  /// out-of-line slow case for operator|=.
>> -  void OrAssignSlowCase(const APInt& RHS);
>> -
>> -  /// out-of-line slow case for operator^=.
>> -  void XorAssignSlowCase(const APInt& RHS);
>> -
>> -  /// Unsigned comparison. Returns -1, 0, or 1 if this APInt is less
>> than, equal
>> -  /// to, or greater than RHS.
>> -  int compare(const APInt &RHS) const LLVM_READONLY;
>> -
>> -  /// Signed comparison. Returns -1, 0, or 1 if this APInt is less than,
>> equal
>> -  /// to, or greater than RHS.
>> -  int compareSigned(const APInt &RHS) const LLVM_READONLY;
>> -
>> -public:
>>    /// \name Constructors
>>    /// @{
>>
>> @@ -312,7 +142,13 @@ class LLVM_NODISCARD APInt {
>>    /// \param radix the radix to use for the conversion
>>    APInt(unsigned numBits, StringRef str, uint8_t radix);
>>
>> -  /// Simply makes *this a copy of that.
>> +  /// Default constructor that creates an uninteresting APInt
>> +  /// representing a 1-bit zero value.
>> +  ///
>> +  /// This is useful for object deserialization (pair this with the
>> static
>> +  ///  method Read).
>> +  explicit APInt() : BitWidth(1) { U.VAL = 0; }
>> +
>>    /// Copy Constructor.
>>    APInt(const APInt &that) : BitWidth(that.BitWidth) {
>>      if (isSingleWord())
>> @@ -333,19 +169,135 @@ class LLVM_NODISCARD APInt {
>>        delete[] U.pVal;
>>    }
>>
>> -  /// Default constructor that creates an uninteresting APInt
>> -  /// representing a 1-bit zero value.
>> +  /// @}
>> +  /// \name Value Generators
>> +  /// @{
>> +
>> +  /// Get the '0' value.
>>    ///
>> -  /// This is useful for object deserialization (pair this with the
>> static
>> -  ///  method Read).
>> -  explicit APInt() : BitWidth(1) { U.VAL = 0; }
>> +  /// \returns the '0' value for an APInt of the specified bit-width.
>> +  static APInt getNullValue(unsigned numBits) { return APInt(numBits,
>> 0); }
>>
>> -  /// Returns whether this instance allocated memory.
>> -  bool needsCleanup() const { return !isSingleWord(); }
>> +  /// Gets maximum unsigned value of APInt for specific bit width.
>> +  static APInt getMaxValue(unsigned numBits) {
>> +    return getAllOnesValue(numBits);
>> +  }
>>
>> -  /// Used to insert APInt objects, or objects that contain APInt
>> objects, into
>> -  ///  FoldingSets.
>> -  void Profile(FoldingSetNodeID &id) const;
>> +  /// Gets maximum signed value of APInt for a specific bit width.
>> +  static APInt getSignedMaxValue(unsigned numBits) {
>> +    APInt API = getAllOnesValue(numBits);
>> +    API.clearBit(numBits - 1);
>> +    return API;
>> +  }
>> +
>> +  /// Gets minimum unsigned value of APInt for a specific bit width.
>> +  static APInt getMinValue(unsigned numBits) { return APInt(numBits, 0);
>> }
>> +
>> +  /// Gets minimum signed value of APInt for a specific bit width.
>> +  static APInt getSignedMinValue(unsigned numBits) {
>> +    APInt API(numBits, 0);
>> +    API.setBit(numBits - 1);
>> +    return API;
>> +  }
>> +
>> +  /// Get the SignMask for a specific bit width.
>> +  ///
>> +  /// This is just a wrapper function of getSignedMinValue(), and it
>> helps code
>> +  /// readability when we want to get a SignMask.
>> +  static APInt getSignMask(unsigned BitWidth) {
>> +    return getSignedMinValue(BitWidth);
>> +  }
>> +
>> +  /// Get the all-ones value.
>> +  ///
>> +  /// \returns the all-ones value for an APInt of the specified
>> bit-width.
>> +  static APInt getAllOnesValue(unsigned numBits) {
>> +    return APInt(numBits, WORDTYPE_MAX, true);
>> +  }
>> +
>> +  /// Return an APInt with exactly one bit set in the result.
>> +  static APInt getOneBitSet(unsigned numBits, unsigned BitNo) {
>> +    APInt Res(numBits, 0);
>> +    Res.setBit(BitNo);
>> +    return Res;
>> +  }
>> +
>> +  /// Get a value with a block of bits set.
>> +  ///
>> +  /// Constructs an APInt value that has a contiguous range of bits set.
>> The
>> +  /// bits from loBit (inclusive) to hiBit (exclusive) will be set. All
>> other
>> +  /// bits will be zero. For example, with parameters(32, 0, 16) you
>> would get
>> +  /// 0x0000FFFF. Please call getBitsSetWithWrap if \p loBit may be
>> greater than
>> +  /// \p hiBit.
>> +  ///
>> +  /// \param numBits the intended bit width of the result
>> +  /// \param loBit the index of the lowest bit set.
>> +  /// \param hiBit the index of the highest bit set.
>> +  ///
>> +  /// \returns An APInt value with the requested bits set.
>> +  static APInt getBitsSet(unsigned numBits, unsigned loBit, unsigned
>> hiBit) {
>> +    assert(loBit <= hiBit && "loBit greater than hiBit");
>> +    APInt Res(numBits, 0);
>> +    Res.setBits(loBit, hiBit);
>> +    return Res;
>> +  }
>> +
>> +  /// Wrap version of getBitsSet.
>> +  /// If \p hiBit is bigger than \p loBit, this is same with getBitsSet.
>> +  /// If \p hiBit is not bigger than \p loBit, the set bits "wrap". For
>> example,
>> +  /// with parameters (32, 28, 4), you would get 0xF000000F.
>> +  /// If \p hiBit is equal to \p loBit, you would get a result with all
>> bits
>> +  /// set.
>> +  static APInt getBitsSetWithWrap(unsigned numBits, unsigned loBit,
>> +                                  unsigned hiBit) {
>> +    APInt Res(numBits, 0);
>> +    Res.setBitsWithWrap(loBit, hiBit);
>> +    return Res;
>> +  }
>> +
>> +  /// Get a value with upper bits starting at loBit set.
>> +  ///
>> +  /// Constructs an APInt value that has a contiguous range of bits set.
>> The
>> +  /// bits from loBit (inclusive) to numBits (exclusive) will be set.
>> All other
>> +  /// bits will be zero. For example, with parameters(32, 12) you would
>> get
>> +  /// 0xFFFFF000.
>> +  ///
>> +  /// \param numBits the intended bit width of the result
>> +  /// \param loBit the index of the lowest bit to set.
>> +  ///
>> +  /// \returns An APInt value with the requested bits set.
>> +  static APInt getBitsSetFrom(unsigned numBits, unsigned loBit) {
>> +    APInt Res(numBits, 0);
>> +    Res.setBitsFrom(loBit);
>> +    return Res;
>> +  }
>> +
>> +  /// Get a value with high bits set
>> +  ///
>> +  /// Constructs an APInt value that has the top hiBitsSet bits set.
>> +  ///
>> +  /// \param numBits the bitwidth of the result
>> +  /// \param hiBitsSet the number of high-order bits set in the result.
>> +  static APInt getHighBitsSet(unsigned numBits, unsigned hiBitsSet) {
>> +    APInt Res(numBits, 0);
>> +    Res.setHighBits(hiBitsSet);
>> +    return Res;
>> +  }
>> +
>> +  /// Get a value with low bits set
>> +  ///
>> +  /// Constructs an APInt value that has the bottom loBitsSet bits set.
>> +  ///
>> +  /// \param numBits the bitwidth of the result
>> +  /// \param loBitsSet the number of low-order bits set in the result.
>> +  static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet) {
>> +    APInt Res(numBits, 0);
>> +    Res.setLowBits(loBitsSet);
>> +    return Res;
>> +  }
>> +
>> +  /// Return a value containing V broadcasted over NewLen bits.
>> +  static APInt getSplat(unsigned NewLen, const APInt &V);
>>
>>    /// @}
>>    /// \name Value Tests
>> @@ -373,7 +325,7 @@ class LLVM_NODISCARD APInt {
>>    /// This tests the high bit of this APInt to determine if it is set.
>>    ///
>>    /// \returns true if this APInt has its sign bit set, false otherwise.
>> -  bool isSignBitSet() const { return (*this)[BitWidth-1]; }
>> +  bool isSignBitSet() const { return (*this)[BitWidth - 1]; }
>>
>>    /// Determine if sign bit of this APInt is clear.
>>    ///
>> @@ -453,13 +405,13 @@ class LLVM_NODISCARD APInt {
>>
>>    /// Check if this APInt has an N-bits unsigned integer value.
>>    bool isIntN(unsigned N) const {
>> -    assert(N && "N == 0 ???");
>> +    assert(N && "0 bit APInt not supported");
>>      return getActiveBits() <= N;
>>    }
>>
>>    /// Check if this APInt has an N-bits signed integer value.
>>    bool isSignedIntN(unsigned N) const {
>> -    assert(N && "N == 0 ???");
>> +    assert(N && "0 bit APInt not supported");
>>      return getMinSignedBits() <= N;
>>    }
>>
>> @@ -498,180 +450,50 @@ class LLVM_NODISCARD APInt {
>>    /// \returns true if this 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 U.VAL == (WORDTYPE_MAX >> (APINT_BITS_PER_WORD - numBits));
>> -    unsigned Ones = countTrailingOnesSlowCase();
>> -    return (numBits == Ones) &&
>> -           ((Ones + countLeadingZerosSlowCase()) == BitWidth);
>> -  }
>> -
>> -  /// \returns true if this APInt 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(U.VAL);
>> -    unsigned Ones = countTrailingOnesSlowCase();
>> -    return (Ones > 0) && ((Ones + countLeadingZerosSlowCase()) ==
>> BitWidth);
>> -  }
>> -
>> -  /// Return true if this APInt value contains a sequence of ones with
>> -  /// the remainder zero.
>> -  bool isShiftedMask() const {
>> -    if (isSingleWord())
>> -      return isShiftedMask_64(U.VAL);
>> -    unsigned Ones = countPopulationSlowCase();
>> -    unsigned LeadZ = countLeadingZerosSlowCase();
>> -    return (Ones + LeadZ + countTrailingZeros()) == BitWidth;
>> -  }
>> -
>> -  /// @}
>> -  /// \name Value Generators
>> -  /// @{
>> -
>> -  /// Gets maximum unsigned value of APInt for specific bit width.
>> -  static APInt getMaxValue(unsigned numBits) {
>> -    return getAllOnesValue(numBits);
>> -  }
>> -
>> -  /// Gets maximum signed value of APInt for a specific bit width.
>> -  static APInt getSignedMaxValue(unsigned numBits) {
>> -    APInt API = getAllOnesValue(numBits);
>> -    API.clearBit(numBits - 1);
>> -    return API;
>> -  }
>> -
>> -  /// Gets minimum unsigned value of APInt for a specific bit width.
>> -  static APInt getMinValue(unsigned numBits) { return APInt(numBits, 0);
>> }
>> -
>> -  /// Gets minimum signed value of APInt for a specific bit width.
>> -  static APInt getSignedMinValue(unsigned numBits) {
>> -    APInt API(numBits, 0);
>> -    API.setBit(numBits - 1);
>> -    return API;
>> -  }
>> -
>> -  /// Get the SignMask for a specific bit width.
>> -  ///
>> -  /// This is just a wrapper function of getSignedMinValue(), and it
>> helps code
>> -  /// readability when we want to get a SignMask.
>> -  static APInt getSignMask(unsigned BitWidth) {
>> -    return getSignedMinValue(BitWidth);
>> -  }
>> -
>> -  /// Get the all-ones value.
>> -  ///
>> -  /// \returns the all-ones value for an APInt of the specified
>> bit-width.
>> -  static APInt getAllOnesValue(unsigned numBits) {
>> -    return APInt(numBits, WORDTYPE_MAX, true);
>> -  }
>> -
>> -  /// Get the '0' value.
>> -  ///
>> -  /// \returns the '0' value for an APInt of the specified bit-width.
>> -  static APInt getNullValue(unsigned numBits) { return APInt(numBits,
>> 0); }
>> -
>> -  /// Compute an APInt containing numBits highbits from this APInt.
>> -  ///
>> -  /// Get an APInt with the same BitWidth as this APInt, just zero mask
>> -  /// the low bits and right shift to the least significant bit.
>> -  ///
>> -  /// \returns the high "numBits" bits of this APInt.
>> -  APInt getHiBits(unsigned numBits) const;
>> -
>> -  /// Compute an APInt containing numBits lowbits from this APInt.
>> -  ///
>> -  /// Get an APInt with the same BitWidth as this APInt, just zero mask
>> -  /// the high bits.
>> -  ///
>> -  /// \returns the low "numBits" bits of this APInt.
>> -  APInt getLoBits(unsigned numBits) const;
>> -
>> -  /// Return an APInt with exactly one bit set in the result.
>> -  static APInt getOneBitSet(unsigned numBits, unsigned BitNo) {
>> -    APInt Res(numBits, 0);
>> -    Res.setBit(BitNo);
>> -    return Res;
>> -  }
>> -
>> -  /// Get a value with a block of bits set.
>> -  ///
>> -  /// Constructs an APInt value that has a contiguous range of bits set.
>> The
>> -  /// bits from loBit (inclusive) to hiBit (exclusive) will be set. All
>> other
>> -  /// bits will be zero. For example, with parameters(32, 0, 16) you
>> would get
>> -  /// 0x0000FFFF. Please call getBitsSetWithWrap if \p loBit may be
>> greater than
>> -  /// \p hiBit.
>> -  ///
>> -  /// \param numBits the intended bit width of the result
>> -  /// \param loBit the index of the lowest bit set.
>> -  /// \param hiBit the index of the highest bit set.
>> -  ///
>> -  /// \returns An APInt value with the requested bits set.
>> -  static APInt getBitsSet(unsigned numBits, unsigned loBit, unsigned
>> hiBit) {
>> -    assert(loBit <= hiBit && "loBit greater than hiBit");
>> -    APInt Res(numBits, 0);
>> -    Res.setBits(loBit, hiBit);
>> -    return Res;
>> +    assert(numBits != 0 && "numBits must be non-zero");
>> +    assert(numBits <= BitWidth && "numBits out of range");
>> +    if (isSingleWord())
>> +      return U.VAL == (WORDTYPE_MAX >> (APINT_BITS_PER_WORD - numBits));
>> +    unsigned Ones = countTrailingOnesSlowCase();
>> +    return (numBits == Ones) &&
>> +           ((Ones + countLeadingZerosSlowCase()) == BitWidth);
>>    }
>>
>> -  /// Wrap version of getBitsSet.
>> -  /// If \p hiBit is bigger than \p loBit, this is same with getBitsSet.
>> -  /// If \p hiBit is not bigger than \p loBit, the set bits "wrap". For
>> example,
>> -  /// with parameters (32, 28, 4), you would get 0xF000000F.
>> -  /// If \p hiBit is equal to \p loBit, you would get a result with all
>> bits
>> -  /// set.
>> -  static APInt getBitsSetWithWrap(unsigned numBits, unsigned loBit,
>> -                                  unsigned hiBit) {
>> -    APInt Res(numBits, 0);
>> -    Res.setBitsWithWrap(loBit, hiBit);
>> -    return Res;
>> +  /// \returns true if this APInt 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(U.VAL);
>> +    unsigned Ones = countTrailingOnesSlowCase();
>> +    return (Ones > 0) && ((Ones + countLeadingZerosSlowCase()) ==
>> BitWidth);
>>    }
>>
>> -  /// Get a value with upper bits starting at loBit set.
>> -  ///
>> -  /// Constructs an APInt value that has a contiguous range of bits set.
>> The
>> -  /// bits from loBit (inclusive) to numBits (exclusive) will be set.
>> All other
>> -  /// bits will be zero. For example, with parameters(32, 12) you would
>> get
>> -  /// 0xFFFFF000.
>> -  ///
>> -  /// \param numBits the intended bit width of the result
>> -  /// \param loBit the index of the lowest bit to set.
>> -  ///
>> -  /// \returns An APInt value with the requested bits set.
>> -  static APInt getBitsSetFrom(unsigned numBits, unsigned loBit) {
>> -    APInt Res(numBits, 0);
>> -    Res.setBitsFrom(loBit);
>> -    return Res;
>> +  /// Return true if this APInt value contains a sequence of ones with
>> +  /// the remainder zero.
>> +  bool isShiftedMask() const {
>> +    if (isSingleWord())
>> +      return isShiftedMask_64(U.VAL);
>> +    unsigned Ones = countPopulationSlowCase();
>> +    unsigned LeadZ = countLeadingZerosSlowCase();
>> +    return (Ones + LeadZ + countTrailingZeros()) == BitWidth;
>>    }
>>
>> -  /// Get a value with high bits set
>> +  /// Compute an APInt containing numBits highbits from this APInt.
>>    ///
>> -  /// Constructs an APInt value that has the top hiBitsSet bits set.
>> +  /// Get an APInt with the same BitWidth as this APInt, just zero mask
>> +  /// the low bits and right shift to the least significant bit.
>>    ///
>> -  /// \param numBits the bitwidth of the result
>> -  /// \param hiBitsSet the number of high-order bits set in the result.
>> -  static APInt getHighBitsSet(unsigned numBits, unsigned hiBitsSet) {
>> -    APInt Res(numBits, 0);
>> -    Res.setHighBits(hiBitsSet);
>> -    return Res;
>> -  }
>> +  /// \returns the high "numBits" bits of this APInt.
>> +  APInt getHiBits(unsigned numBits) const;
>>
>> -  /// Get a value with low bits set
>> +  /// Compute an APInt containing numBits lowbits from this APInt.
>>    ///
>> -  /// Constructs an APInt value that has the bottom loBitsSet bits set.
>> +  /// Get an APInt with the same BitWidth as this APInt, just zero mask
>> +  /// the high bits.
>>    ///
>> -  /// \param numBits the bitwidth of the result
>> -  /// \param loBitsSet the number of low-order bits set in the result.
>> -  static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet) {
>> -    APInt Res(numBits, 0);
>> -    Res.setLowBits(loBitsSet);
>> -    return Res;
>> -  }
>> -
>> -  /// Return a value containing V broadcasted over NewLen bits.
>> -  static APInt getSplat(unsigned NewLen, const APInt &V);
>> +  /// \returns the low "numBits" bits of this APInt.
>> +  APInt getLoBits(unsigned numBits) const;
>>
>>    /// Determine if two APInts have the same value, after zero-extending
>>    /// one of them (if needed!) to ensure that the bit-widths match.
>> @@ -827,7 +649,7 @@ class LLVM_NODISCARD APInt {
>>        return *this;
>>      }
>>      U.pVal[0] &= RHS;
>> -    memset(U.pVal+1, 0, (getNumWords() - 1) * APINT_WORD_SIZE);
>> +    memset(U.pVal + 1, 0, (getNumWords() - 1) * APINT_WORD_SIZE);
>>      return *this;
>>    }
>>
>> @@ -1449,9 +1271,7 @@ class LLVM_NODISCARD APInt {
>>    }
>>
>>    /// Set the sign bit to 1.
>> -  void setSignBit() {
>> -    setBit(BitWidth - 1);
>> -  }
>> +  void setSignBit() { setBit(BitWidth - 1); }
>>
>>    /// Set a given bit to a given value.
>>    void setBitVal(unsigned BitPosition, bool BitValue) {
>> @@ -1497,14 +1317,10 @@ class LLVM_NODISCARD APInt {
>>    }
>>
>>    /// Set the top bits starting from loBit.
>> -  void setBitsFrom(unsigned loBit) {
>> -    return setBits(loBit, BitWidth);
>> -  }
>> +  void setBitsFrom(unsigned loBit) { return setBits(loBit, BitWidth); }
>>
>>    /// Set the bottom loBits bits.
>> -  void setLowBits(unsigned loBits) {
>> -    return setBits(0, loBits);
>> -  }
>> +  void setLowBits(unsigned loBits) { return setBits(0, loBits); }
>>
>>    /// Set the top hiBits bits.
>>    void setHighBits(unsigned hiBits) {
>> @@ -1539,9 +1355,7 @@ class LLVM_NODISCARD APInt {
>>    }
>>
>>    /// Set the sign bit to 0.
>> -  void clearSignBit() {
>> -    clearBit(BitWidth - 1);
>> -  }
>> +  void clearSignBit() { clearBit(BitWidth - 1); }
>>
>>    /// Toggle every bit to its opposite value.
>>    void flipAllBits() {
>> @@ -1774,9 +1588,7 @@ class LLVM_NODISCARD APInt {
>>    /// The conversion does not do a translation from integer to double,
>> it just
>>    /// re-interprets the bits as a double. Note that it is valid to do
>> this on
>>    /// any bit width. Exactly 64 bits will be translated.
>> -  double bitsToDouble() const {
>> -    return BitsToDouble(getWord(0));
>> -  }
>> +  double bitsToDouble() const { return BitsToDouble(getWord(0)); }
>>
>>    /// Converts APInt bits to a float
>>    ///
>> @@ -1808,7 +1620,7 @@ class LLVM_NODISCARD APInt {
>>    /// @{
>>
>>    /// \returns the floor log base 2 of this APInt.
>> -  unsigned logBase2() const { return getActiveBits() -  1; }
>> +  unsigned logBase2() const { return getActiveBits() - 1; }
>>
>>    /// \returns the ceil log base 2 of this APInt.
>>    unsigned ceilLogBase2() const {
>> @@ -1908,9 +1720,8 @@ class LLVM_NODISCARD APInt {
>>    /// DST, of dstCOUNT parts, such that the bit srcLSB becomes the least
>>    /// significant bit of DST.  All high bits above srcBITS in DST are
>>    /// zero-filled.
>> -  static void tcExtract(WordType *, unsigned dstCount,
>> -                        const WordType *, unsigned srcBits,
>> -                        unsigned srcLSB);
>> +  static void tcExtract(WordType *, unsigned dstCount, const WordType *,
>> +                        unsigned srcBits, unsigned srcLSB);
>>
>>    /// Set the given bit of a bignum.  Zero-based.
>>    static void tcSetBit(WordType *, unsigned bit);
>> @@ -1927,14 +1738,13 @@ class LLVM_NODISCARD APInt {
>>    static void tcNegate(WordType *, unsigned);
>>
>>    /// DST += RHS + CARRY where CARRY is zero or one.  Returns the carry
>> flag.
>> -  static WordType tcAdd(WordType *, const WordType *,
>> -                        WordType carry, unsigned);
>> +  static WordType tcAdd(WordType *, const WordType *, WordType carry,
>> unsigned);
>>    /// DST += RHS.  Returns the carry flag.
>>    static WordType tcAddPart(WordType *, WordType, unsigned);
>>
>>    /// DST -= RHS + CARRY where CARRY is zero or one. Returns the carry
>> flag.
>> -  static WordType tcSubtract(WordType *, const WordType *,
>> -                             WordType carry, unsigned);
>> +  static WordType tcSubtract(WordType *, const WordType *, WordType
>> carry,
>> +                             unsigned);
>>    /// DST -= RHS.  Returns the carry flag.
>>    static WordType tcSubtractPart(WordType *, WordType, unsigned);
>>
>> @@ -1950,8 +1760,7 @@ class LLVM_NODISCARD APInt {
>>    /// otherwise overflow occurred and return one.
>>    static int tcMultiplyPart(WordType *dst, const WordType *src,
>>                              WordType multiplier, WordType carry,
>> -                            unsigned srcParts, unsigned dstParts,
>> -                            bool add);
>> +                            unsigned srcParts, unsigned dstParts, bool
>> add);
>>
>>    /// DST = LHS * RHS, where DST has the same width as the operands and
>> is
>>    /// filled with the least significant parts of the result.  Returns
>> one if
>> @@ -1962,8 +1771,8 @@ class LLVM_NODISCARD APInt {
>>
>>    /// DST = LHS * RHS, where DST has width the sum of the widths of the
>>    /// operands. No overflow occurs. DST must be disjoint from both
>> operands.
>> -  static void tcFullMultiply(WordType *, const WordType *,
>> -                             const WordType *, unsigned, unsigned);
>> +  static void tcFullMultiply(WordType *, const WordType *, const
>> WordType *,
>> +                             unsigned, unsigned);
>>
>>    /// If RHS is zero LHS and REMAINDER are left unchanged, return one.
>>    /// Otherwise set LHS to LHS / RHS with the fractional part discarded,
>> set
>> @@ -1974,9 +1783,8 @@ class LLVM_NODISCARD APInt {
>>    /// SCRATCH is a bignum of the same size as the operands and result
>> for use by
>>    /// the routine; its contents need not be initialized and are
>> destroyed.  LHS,
>>    /// REMAINDER and SCRATCH must be distinct.
>> -  static int tcDivide(WordType *lhs, const WordType *rhs,
>> -                      WordType *remainder, WordType *scratch,
>> -                      unsigned parts);
>> +  static int tcDivide(WordType *lhs, const WordType *rhs, WordType
>> *remainder,
>> +                      WordType *scratch, unsigned parts);
>>
>>    /// Shift a bignum left Count bits. Shifted in bits are zero. There
>> are no
>>    /// restrictions on Count.
>> @@ -2008,9 +1816,183 @@ class LLVM_NODISCARD APInt {
>>    /// Set the least significant BITS and clear the rest.
>>    static void tcSetLeastSignificantBits(WordType *, unsigned, unsigned
>> bits);
>>
>> +  /// Used to insert APInt objects, or objects that contain APInt
>> objects, into
>> +  ///  FoldingSets.
>> +  void Profile(FoldingSetNodeID &id) const;
>> +
>>    /// debug method
>>    void dump() const;
>>
>> +private:
>> +  /// This union is used to store the integer value. When the
>> +  /// integer bit-width <= 64, it uses VAL, otherwise it uses pVal.
>> +  union {
>> +    uint64_t VAL;   ///< Used to store the <= 64 bits integer value.
>> +    uint64_t *pVal; ///< Used to store the >64 bits integer value.
>> +  } U;
>> +
>> +  unsigned BitWidth; ///< The number of bits in this APInt.
>> +
>> +  friend struct DenseMapInfo<APInt>;
>> +
>> +  friend class APSInt;
>> +
>> +  /// Fast internal constructor
>> +  ///
>> +  /// This constructor is used only internally for speed of construction
>> of
>> +  /// temporaries. It is unsafe for general use so it is not public.
>> +  APInt(uint64_t *val, unsigned bits) : BitWidth(bits) { U.pVal = val; }
>> +
>> +  /// Determine which word a bit is in.
>> +  ///
>> +  /// \returns the word position for the specified bit position.
>> +  static unsigned whichWord(unsigned bitPosition) {
>> +    return bitPosition / APINT_BITS_PER_WORD;
>> +  }
>> +
>> +  /// Determine which bit in a word a bit is in.
>> +  ///
>> +  /// \returns the bit position in a word for the specified bit position
>> +  /// in the APInt.
>> +  static unsigned whichBit(unsigned bitPosition) {
>> +    return bitPosition % APINT_BITS_PER_WORD;
>> +  }
>> +
>> +  /// Get a single bit mask.
>> +  ///
>> +  /// \returns a uint64_t with only bit at "whichBit(bitPosition)" set
>> +  /// This method generates and returns a uint64_t (word) mask for a
>> single
>> +  /// bit at a specific bit position. This is used to mask the bit in the
>> +  /// corresponding word.
>> +  static uint64_t maskBit(unsigned bitPosition) {
>> +    return 1ULL << whichBit(bitPosition);
>> +  }
>> +
>> +  /// Clear unused high order bits
>> +  ///
>> +  /// This method is used internally to clear the top "N" bits in the
>> high order
>> +  /// word that are not used by the APInt. This is needed after the most
>> +  /// significant word is assigned a value to ensure that those bits are
>> +  /// zero'd out.
>> +  APInt &clearUnusedBits() {
>> +    // Compute how many bits are used in the final word
>> +    unsigned WordBits = ((BitWidth - 1) % APINT_BITS_PER_WORD) + 1;
>> +
>> +    // Mask out the high bits.
>> +    uint64_t mask = WORDTYPE_MAX >> (APINT_BITS_PER_WORD - WordBits);
>> +    if (isSingleWord())
>> +      U.VAL &= mask;
>> +    else
>> +      U.pVal[getNumWords() - 1] &= mask;
>> +    return *this;
>> +  }
>> +
>> +  /// Get the word corresponding to a bit position
>> +  /// \returns the corresponding word for the specified bit position.
>> +  uint64_t getWord(unsigned bitPosition) const {
>> +    return isSingleWord() ? U.VAL : U.pVal[whichWord(bitPosition)];
>> +  }
>> +
>> +  /// Utility method to change the bit width of this APInt to new bit
>> width,
>> +  /// allocating and/or deallocating as necessary. There is no guarantee
>> on the
>> +  /// value of any bits upon return. Caller should populate the bits
>> after.
>> +  void reallocate(unsigned NewBitWidth);
>> +
>> +  /// Convert a char array into an APInt
>> +  ///
>> +  /// \param radix 2, 8, 10, 16, or 36
>> +  /// Converts a string into a number.  The string must be non-empty
>> +  /// and well-formed as a number of the given base. The bit-width
>> +  /// must be sufficient to hold the result.
>> +  ///
>> +  /// This is used by the constructors that take string arguments.
>> +  ///
>> +  /// StringRef::getAsInteger is superficially similar but (1) does
>> +  /// not assume that the string is well-formed and (2) grows the
>> +  /// result to hold the input.
>> +  void fromString(unsigned numBits, StringRef str, uint8_t radix);
>> +
>> +  /// An internal division function for dividing APInts.
>> +  ///
>> +  /// This is used by the toString method to divide by the radix. It
>> simply
>> +  /// provides a more convenient form of divide for internal use since
>> KnuthDiv
>> +  /// has specific constraints on its inputs. If those constraints are
>> not met
>> +  /// then it provides a simpler form of divide.
>> +  static void divide(const WordType *LHS, unsigned lhsWords,
>> +                     const WordType *RHS, unsigned rhsWords, WordType
>> *Quotient,
>> +                     WordType *Remainder);
>> +
>> +  /// out-of-line slow case for inline constructor
>> +  void initSlowCase(uint64_t val, bool isSigned);
>> +
>> +  /// shared code between two array constructors
>> +  void initFromArray(ArrayRef<uint64_t> array);
>> +
>> +  /// out-of-line slow case for inline copy constructor
>> +  void initSlowCase(const APInt &that);
>> +
>> +  /// out-of-line slow case for shl
>> +  void shlSlowCase(unsigned ShiftAmt);
>> +
>> +  /// out-of-line slow case for lshr.
>> +  void lshrSlowCase(unsigned ShiftAmt);
>> +
>> +  /// out-of-line slow case for ashr.
>> +  void ashrSlowCase(unsigned ShiftAmt);
>> +
>> +  /// out-of-line slow case for operator=
>> +  void AssignSlowCase(const APInt &RHS);
>> +
>> +  /// out-of-line slow case for operator==
>> +  bool EqualSlowCase(const APInt &RHS) const LLVM_READONLY;
>> +
>> +  /// out-of-line slow case for countLeadingZeros
>> +  unsigned countLeadingZerosSlowCase() const LLVM_READONLY;
>> +
>> +  /// out-of-line slow case for countLeadingOnes.
>> +  unsigned countLeadingOnesSlowCase() const LLVM_READONLY;
>> +
>> +  /// out-of-line slow case for countTrailingZeros.
>> +  unsigned countTrailingZerosSlowCase() const LLVM_READONLY;
>> +
>> +  /// out-of-line slow case for countTrailingOnes
>> +  unsigned countTrailingOnesSlowCase() const LLVM_READONLY;
>> +
>> +  /// out-of-line slow case for countPopulation
>> +  unsigned countPopulationSlowCase() const LLVM_READONLY;
>> +
>> +  /// out-of-line slow case for intersects.
>> +  bool intersectsSlowCase(const APInt &RHS) const LLVM_READONLY;
>> +
>> +  /// out-of-line slow case for isSubsetOf.
>> +  bool isSubsetOfSlowCase(const APInt &RHS) const LLVM_READONLY;
>> +
>> +  /// out-of-line slow case for setBits.
>> +  void setBitsSlowCase(unsigned loBit, unsigned hiBit);
>> +
>> +  /// out-of-line slow case for flipAllBits.
>> +  void flipAllBitsSlowCase();
>> +
>> +  /// out-of-line slow case for operator&=.
>> +  void AndAssignSlowCase(const APInt &RHS);
>> +
>> +  /// out-of-line slow case for operator|=.
>> +  void OrAssignSlowCase(const APInt &RHS);
>> +
>> +  /// out-of-line slow case for operator^=.
>> +  void XorAssignSlowCase(const APInt &RHS);
>> +
>> +  /// Unsigned comparison. Returns -1, 0, or 1 if this APInt is less
>> than, equal
>> +  /// to, or greater than RHS.
>> +  int compare(const APInt &RHS) const LLVM_READONLY;
>> +
>> +  /// Signed comparison. Returns -1, 0, or 1 if this APInt is less than,
>> equal
>> +  /// to, or greater than RHS.
>> +  int compareSigned(const APInt &RHS) const LLVM_READONLY;
>> +
>> +  /// Returns whether this instance allocated memory.
>> +  bool needsCleanup() const { return !isSingleWord(); }
>> +
>>    /// @}
>>  };
>>
>> @@ -2161,7 +2143,6 @@ inline APInt operator*(uint64_t LHS, APInt b) {
>>    return b;
>>  }
>>
>> -
>>  namespace APIntOps {
>>
>>  /// Determine the smaller of two APInts considered to be signed.
>> @@ -2277,7 +2258,7 @@ Optional<APInt> SolveQuadraticEquationWrap(APInt A,
>> APInt B, APInt C,
>>  Optional<unsigned> GetMostSignificantDifferentBit(const APInt &A,
>>                                                    const APInt &B);
>>
>> -} // End of APIntOps namespace
>> +} // namespace APIntOps
>>
>>  // See friend declaration above. This additional declaration is required
>> in
>>  // order to compile LLVM with IBM xlC compiler.
>>
>>
>>
>> _______________________________________________
>> llvm-commits mailing list
>> llvm-commits at lists.llvm.org
>> https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20210908/fd4482e2/attachment-0001.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/pkcs7-signature
Size: 3992 bytes
Desc: S/MIME Cryptographic Signature
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20210908/fd4482e2/attachment-0001.bin>


More information about the llvm-commits mailing list