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