mirror of
https://github.com/RPCS3/llvm.git
synced 2026-07-19 15:13:49 -04:00
[APInt] Add APInt::setBits() method to set all bits in range
The current pattern for setting bits in range is typically: Mask |= APInt::getBitsSet(MaskSizeInBits, LoPos, HiPos); Which can be particularly slow for large APInts (MaskSizeInBits > 64) as they require the allocation memory for the temporary variable. This is one of the key compile time issues identified in PR32037. This patch adds the APInt::setBits() helper method which avoids the temporary memory allocation completely, this first implementation uses setBit() internally instead but already significantly reduces the regression in PR32037 (~10% drop). Additional optimization may be possible. I investigated whether there is need for APInt::clearBits() and APInt::flipBits() equivalents but haven't seen these patterns to be particularly common, but reusing the code would be trivial. Differential Revision: https://reviews.llvm.org/D30265 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@296102 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -565,6 +565,39 @@ void APInt::setBit(unsigned bitPosition) {
|
||||
pVal[whichWord(bitPosition)] |= maskBit(bitPosition);
|
||||
}
|
||||
|
||||
void APInt::setBits(unsigned loBit, unsigned hiBit) {
|
||||
assert(hiBit <= BitWidth && "hiBit out of range");
|
||||
assert(loBit <= hiBit && loBit <= BitWidth && "loBit out of range");
|
||||
|
||||
if (loBit == hiBit)
|
||||
return;
|
||||
|
||||
if (isSingleWord())
|
||||
*this |= APInt::getBitsSet(BitWidth, loBit, hiBit);
|
||||
else {
|
||||
unsigned hiBit1 = hiBit - 1;
|
||||
unsigned loWord = whichWord(loBit);
|
||||
unsigned hiWord = whichWord(hiBit1);
|
||||
if (loWord == hiWord) {
|
||||
// Set bits are all within the same word, create a [loBit,hiBit) mask.
|
||||
uint64_t mask = UINT64_MAX;
|
||||
mask >>= (APINT_BITS_PER_WORD - (hiBit - loBit));
|
||||
mask <<= whichBit(loBit);
|
||||
pVal[loWord] |= mask;
|
||||
} else {
|
||||
// Set bits span multiple words, create a lo mask with set bits starting
|
||||
// at loBit, a hi mask with set bits below hiBit and set all bits of the
|
||||
// words in between.
|
||||
uint64_t loMask = UINT64_MAX << whichBit(loBit);
|
||||
uint64_t hiMask = UINT64_MAX >> (64 - whichBit(hiBit1) - 1);
|
||||
pVal[loWord] |= loMask;
|
||||
pVal[hiWord] |= hiMask;
|
||||
for (unsigned word = loWord + 1; word < hiWord; ++word)
|
||||
pVal[word] = UINT64_MAX;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Set the given bit to 0 whose position is given as "bitPosition".
|
||||
/// @brief Set a given bit to 0.
|
||||
void APInt::clearBit(unsigned bitPosition) {
|
||||
|
||||
Reference in New Issue
Block a user