From 31acef50ad109d755109bc72a82b14a6aa318f65 Mon Sep 17 00:00:00 2001 From: Reid Spencer Date: Tue, 27 Feb 2007 21:59:26 +0000 Subject: [PATCH] Implement countLeadingOnes() and getMinSignedBits(). This helps to minimize the bit width of negative numbers by computing the minimum bit width for a negative value. E.g. 0x1800000000000000 could be just 0x8000000000000000 llvm-svn: 34695 --- llvm/include/llvm/ADT/APInt.h | 15 ++++++++++++++- llvm/lib/Support/APInt.cpp | 35 ++++++++++++++++++++++++++++++++++- 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/llvm/include/llvm/ADT/APInt.h b/llvm/include/llvm/ADT/APInt.h index 936be5fbd638..51b595b45605 100644 --- a/llvm/include/llvm/ADT/APInt.h +++ b/llvm/include/llvm/ADT/APInt.h @@ -446,6 +446,12 @@ public: return BitWidth - countLeadingZeros(); } + inline uint32_t getMinSignedBits() const { + if (isNegative()) + return BitWidth - countLeadingOnes() + 1; + return getActiveBits(); + } + /// This method attempts to return the value of this APInt as a zero extended /// uint64_t. The bitwidth must be <= 64 or the value must fit within a /// uint64_t. Otherwise an assertion will result. @@ -587,9 +593,16 @@ public: /// @returns getNumWords() * APINT_BITS_PER_WORD if the value is zero. /// @returns the number of zeros from the most significant bit to the first /// one bits. - /// @brief Count the number of trailing one bits. + /// @brief Count the number of leading one bits. uint32_t countLeadingZeros() const; + /// countLeadingOnes - This function counts the number of contiguous 1 bits + /// in the high order bits. The count stops when the first 0 bit is reached. + /// @returns 0 if the high order bit is not set + /// @returns the number of 1 bits from the most significant to the least + /// @brief Count the number of leading one bits. + uint32_t countLeadingOnes() const; + /// countTrailingZeros - This function is an APInt version of the /// countTrailingZoers_{32,64} functions in MathExtras.h. It counts /// the number of zeros from the least significant bit to the first one bit. diff --git a/llvm/lib/Support/APInt.cpp b/llvm/lib/Support/APInt.cpp index acc9de295b40..c13c59e3dbd1 100644 --- a/llvm/lib/Support/APInt.cpp +++ b/llvm/lib/Support/APInt.cpp @@ -702,6 +702,38 @@ uint32_t APInt::countLeadingZeros() const { return Count; } +static uint32_t countLeadingOnes_64(uint64_t V, uint32_t skip) { + uint32_t Count = 0; + if (skip) + V <<= skip; + while (V && (V & (1ULL << 63))) { + Count++; + V <<= 1; + } + return Count; +} + +uint32_t APInt::countLeadingOnes() const { + if (isSingleWord()) + return countLeadingOnes_64(VAL, APINT_BITS_PER_WORD - BitWidth); + + uint32_t highWordBits = BitWidth % APINT_BITS_PER_WORD; + uint32_t shift = (highWordBits == 0 ? 0 : APINT_BITS_PER_WORD - highWordBits); + int i = getNumWords() - 1; + uint32_t Count = countLeadingOnes_64(pVal[i], shift); + if (Count == highWordBits) { + for (i--; i >= 0; --i) { + if (pVal[i] == -1ULL) + Count += APINT_BITS_PER_WORD; + else { + Count += countLeadingOnes_64(pVal[i], 0); + break; + } + } + } + return Count; +} + uint32_t APInt::countTrailingZeros() const { if (isSingleWord()) return CountTrailingZeros_64(VAL); @@ -1701,6 +1733,7 @@ void APInt::dump() const else for (unsigned i = getNumWords(); i > 0; i--) { cerr << pVal[i-1] << " "; } - cerr << " (" << this->toString(10) << ")\n" << std::setbase(10); + cerr << " U(" << this->toString(10) << ") S(" << this->toStringSigned(10) + << ")\n" << std::setbase(10); } #endif