Skip to content

Commit 674d256

Browse files
committed
---
yaml --- r: 347895 b: refs/heads/master c: ffa9166 h: refs/heads/master i: 347893: 51f02b5 347891: bf7f285 347887: 0ce3be2
1 parent d004bba commit 674d256

File tree

9 files changed

+158
-223
lines changed

9 files changed

+158
-223
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
refs/heads/master: 598bff9b8306ad74fb4492f9169e217cf78238c3
2+
refs/heads/master: ffa9166efde979e50181aa9eac14a50cbf3ecaff
33
refs/heads/master-next: 203b3026584ecad859eb328b2e12490099409cd5
44
refs/tags/osx-passed: b6b74147ef8a386f532cf9357a1bde006e552c54
55
refs/tags/swift-2.2-SNAPSHOT-2015-12-01-a: 6bb18e013c2284f2b45f5f84f2df2887dc0f7dea

trunk/include/swift/Basic/ClusteredBitVector.h

Lines changed: 0 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -539,48 +539,6 @@ class ClusteredBitVector {
539539
return !any();
540540
}
541541

542-
/// A class for scanning for set bits, from low indices to high ones.
543-
class SetBitEnumerator {
544-
ChunkType CurChunk;
545-
const ChunkType *Chunks;
546-
unsigned CurChunkIndex;
547-
unsigned NumChunks;
548-
public:
549-
explicit SetBitEnumerator(const ClusteredBitVector &vector) {
550-
if (vector.isInlineAndAllClear()) {
551-
CurChunkIndex = 0;
552-
NumChunks = 0;
553-
} else {
554-
Chunks = vector.getChunksPtr();
555-
CurChunk = Chunks[0];
556-
CurChunkIndex = 0;
557-
NumChunks = vector.getLengthInChunks();
558-
}
559-
}
560-
561-
/// Search for another bit. Returns false if it can't find one.
562-
Optional<size_t> findNext() {
563-
if (CurChunkIndex == NumChunks) return None;
564-
auto cur = CurChunk;
565-
while (!cur) {
566-
if (++CurChunkIndex == NumChunks) return None;
567-
cur = Chunks[CurChunkIndex];
568-
}
569-
570-
// Find the index of the lowest set bit.
571-
size_t bitIndex = llvm::countTrailingZeros(cur, llvm::ZB_Undefined);
572-
573-
// Clear that bit in the current chunk.
574-
CurChunk = cur ^ (ChunkType(1) << bitIndex);
575-
assert(!(CurChunk & (ChunkType(1) << bitIndex)));
576-
577-
return (CurChunkIndex * ChunkSizeInBits + bitIndex);
578-
}
579-
};
580-
SetBitEnumerator enumerateSetBits() const {
581-
return SetBitEnumerator(*this);
582-
}
583-
584542
friend bool operator==(const ClusteredBitVector &lhs,
585543
const ClusteredBitVector &rhs) {
586544
if (lhs.size() != rhs.size())

trunk/lib/IRGen/EnumPayload.cpp

Lines changed: 2 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -696,70 +696,6 @@ EnumPayload::emitApplyOrMask(IRGenFunction &IGF,
696696
}
697697
}
698698

699-
/// Gather spare bits into the low bits of a smaller integer value.
700-
llvm::Value *irgen::emitGatherSpareBits(IRGenFunction &IGF,
701-
const SpareBitVector &spareBitMask,
702-
llvm::Value *spareBits,
703-
unsigned resultLowBit,
704-
unsigned resultBitWidth) {
705-
auto destTy
706-
= llvm::IntegerType::get(IGF.IGM.getLLVMContext(), resultBitWidth);
707-
unsigned usedBits = resultLowBit;
708-
llvm::Value *result = nullptr;
709-
710-
auto spareBitEnumeration = spareBitMask.enumerateSetBits();
711-
for (auto optSpareBit = spareBitEnumeration.findNext();
712-
optSpareBit.hasValue() && usedBits < resultBitWidth;
713-
optSpareBit = spareBitEnumeration.findNext()) {
714-
unsigned u = optSpareBit.getValue();
715-
assert(u >= (usedBits - resultLowBit) &&
716-
"used more bits than we've processed?!");
717-
718-
// Shift the bits into place.
719-
llvm::Value *newBits;
720-
if (u > usedBits)
721-
newBits = IGF.Builder.CreateLShr(spareBits, u - usedBits);
722-
else if (u < usedBits) {
723-
newBits = IGF.Builder.CreateZExtOrTrunc(spareBits, destTy);
724-
newBits = IGF.Builder.CreateShl(newBits, usedBits - u);
725-
} else
726-
newBits = spareBits;
727-
newBits = IGF.Builder.CreateZExtOrTrunc(newBits, destTy);
728-
729-
// See how many consecutive bits we have.
730-
unsigned numBits = 1;
731-
++u;
732-
// We don't need more bits than the size of the result.
733-
unsigned maxBits = resultBitWidth - usedBits;
734-
for (unsigned e = spareBitMask.size();
735-
u < e && numBits < maxBits && spareBitMask[u];
736-
++u) {
737-
++numBits;
738-
(void) spareBitEnumeration.findNext();
739-
}
740-
741-
// Mask out the selected bits.
742-
auto val = APInt::getAllOnesValue(numBits);
743-
if (numBits < resultBitWidth)
744-
val = val.zext(resultBitWidth);
745-
val = val.shl(usedBits);
746-
auto *mask = llvm::ConstantInt::get(IGF.IGM.getLLVMContext(), val);
747-
newBits = IGF.Builder.CreateAnd(newBits, mask);
748-
749-
// Accumulate the result.
750-
if (result)
751-
result = IGF.Builder.CreateOr(result, newBits);
752-
else
753-
result = newBits;
754-
755-
usedBits += numBits;
756-
}
757-
758-
return result;
759-
}
760-
761-
762-
763699
llvm::Value *
764700
EnumPayload::emitGatherSpareBits(IRGenFunction &IGF,
765701
const SpareBitVector &spareBits,
@@ -798,8 +734,8 @@ EnumPayload::emitGatherSpareBits(IRGenFunction &IGF,
798734
break;
799735

800736
// Get the spare bits from this part.
801-
auto bits = irgen::emitGatherSpareBits(IGF, spareBitsPart,
802-
v, firstBitOffset, bitWidth);
737+
auto bits = irgen::emitGatherBits(IGF, spareBitsPart.asAPInt(),
738+
v, firstBitOffset, bitWidth);
803739
firstBitOffset += numBitsInPart;
804740

805741
// Accumulate it into the full set.

trunk/lib/IRGen/ExtraInhabitants.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,8 @@ static unsigned getNumLowObjCReservedBits(const IRGenModule &IGM) {
2929
return 0;
3030

3131
// Get the index of the first non-reserved bit.
32-
SpareBitVector ObjCMask = IGM.TargetInfo.ObjCPointerReservedBits;
33-
ObjCMask.flipAll();
34-
return ObjCMask.enumerateSetBits().findNext().getValue();
32+
auto &mask = IGM.TargetInfo.ObjCPointerReservedBits;
33+
return mask.asAPInt().countTrailingOnes();
3534
}
3635

3736
/*****************************************************************************/

trunk/lib/IRGen/GenEnum.cpp

Lines changed: 130 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -6778,62 +6778,141 @@ void irgen::emitStoreEnumTagToAddress(IRGenFunction &IGF,
67786778
.storeTag(IGF, enumTy, enumAddr, theCase);
67796779
}
67806780

6781-
/// Scatter spare bits from the low bits of an integer value.
6782-
llvm::Value *irgen::emitScatterSpareBits(IRGenFunction &IGF,
6783-
const SpareBitVector &spareBitMask,
6784-
llvm::Value *packedBits,
6785-
unsigned packedLowBit) {
6786-
auto destTy
6787-
= llvm::IntegerType::get(IGF.IGM.getLLVMContext(), spareBitMask.size());
6781+
/// Extract the rightmost run of contiguous set bits from the
6782+
/// provided integer or zero if there are no set bits in the
6783+
/// provided integer. For example:
6784+
///
6785+
/// rightmostMask(0x0f0f_0f0f) = 0x0000_000f
6786+
/// rightmostMask(0xf0f0_f0f0) = 0x0000_00f0
6787+
/// rightmostMask(0xffff_ff10) = 0x0000_0010
6788+
/// rightmostMask(0xffff_ff80) = 0xffff_ff80
6789+
/// rightmostMask(0x0000_0000) = 0x0000_0000
6790+
///
6791+
static inline llvm::APInt rightmostMask(const llvm::APInt& mask) {
6792+
if (mask.isShiftedMask()) {
6793+
return mask;
6794+
}
6795+
// This formula is derived from the formula to "turn off the
6796+
// rightmost contiguous string of 1's" in Chapter 2-1 of
6797+
// Hacker's Delight (Second Edition) by Henry S. Warren and
6798+
// attributed to Luther Woodrum.
6799+
llvm::APInt result = -mask;
6800+
result &= mask; // isolate rightmost set bit
6801+
result += mask; // clear rightmost contiguous set bits
6802+
result &= mask; // mask out carry bit leftover from add
6803+
result ^= mask; // extract desired bits
6804+
return result;
6805+
}
6806+
6807+
/// Pack masked bits into the low bits of an integer value.
6808+
/// Equivalent to a parallel bit extract instruction (PEXT),
6809+
/// although we don't currently emit PEXT directly.
6810+
llvm::Value *irgen::emitGatherBits(IRGenFunction &IGF,
6811+
llvm::APInt mask,
6812+
llvm::Value *source,
6813+
unsigned resultLowBit,
6814+
unsigned resultBitWidth) {
6815+
auto &builder = IGF.Builder;
6816+
auto &context = IGF.IGM.getLLVMContext();
6817+
assert(mask.getBitWidth() == source->getType()->getIntegerBitWidth()
6818+
&& "source and mask must have same width");
6819+
6820+
// The source and mask need to be at least as wide as the result so
6821+
// that bits can be shifted into the correct position.
6822+
auto destTy = llvm::IntegerType::get(context, resultBitWidth);
6823+
if (mask.getBitWidth() < resultBitWidth) {
6824+
source = builder.CreateZExt(source, destTy);
6825+
mask = mask.zext(resultBitWidth);
6826+
}
6827+
6828+
// Shift each set of contiguous set bits into position and
6829+
// accumulate them into the result.
6830+
int64_t usedBits = resultLowBit;
67886831
llvm::Value *result = nullptr;
6789-
unsigned usedBits = packedLowBit;
6832+
while (mask != 0) {
6833+
// Isolate the rightmost run of contiguous set bits.
6834+
// Example: 0b0011_01101_1100 -> 0b0000_0001_1100
6835+
llvm::APInt partMask = rightmostMask(mask);
67906836

6791-
// Expand the packed bits to the destination type.
6792-
packedBits = IGF.Builder.CreateZExtOrTrunc(packedBits, destTy);
6793-
6794-
auto spareBitEnumeration = spareBitMask.enumerateSetBits();
6795-
for (auto nextSpareBit = spareBitEnumeration.findNext();
6796-
nextSpareBit.hasValue();
6797-
nextSpareBit = spareBitEnumeration.findNext()) {
6798-
unsigned u = nextSpareBit.getValue(), startBit = u;
6799-
assert(u >= usedBits - packedLowBit
6800-
&& "used more bits than we've processed?!");
6801-
6802-
// Shift the selected bits into place.
6803-
llvm::Value *newBits;
6804-
if (u > usedBits)
6805-
newBits = IGF.Builder.CreateShl(packedBits, u - usedBits);
6806-
else if (u < usedBits)
6807-
newBits = IGF.Builder.CreateLShr(packedBits, usedBits - u);
6808-
else
6809-
newBits = packedBits;
6810-
6811-
// See how many consecutive bits we have.
6812-
unsigned numBits = 1;
6813-
++u;
6814-
for (unsigned e = spareBitMask.size(); u < e && spareBitMask[u]; ++u) {
6815-
++numBits;
6816-
auto nextBit = spareBitEnumeration.findNext(); (void) nextBit;
6817-
assert(nextBit.hasValue());
6818-
}
6819-
6820-
// Mask out the selected bits.
6821-
auto val = APInt::getAllOnesValue(numBits);
6822-
if (numBits < spareBitMask.size())
6823-
val = val.zext(spareBitMask.size());
6824-
val = val.shl(startBit);
6825-
auto mask = llvm::ConstantInt::get(IGF.IGM.getLLVMContext(), val);
6826-
newBits = IGF.Builder.CreateAnd(newBits, mask);
6837+
// Update the bits we need to mask next.
6838+
mask ^= partMask;
6839+
6840+
// Shift the selected bits into position.
6841+
llvm::Value *part = source;
6842+
int64_t offset = int64_t(partMask.countTrailingZeros()) - usedBits;
6843+
if (offset > 0) {
6844+
uint64_t shift = uint64_t(offset);
6845+
part = builder.CreateLShr(part, shift);
6846+
partMask.lshrInPlace(shift);
6847+
} else if (offset < 0) {
6848+
uint64_t shift = uint64_t(-offset);
6849+
part = builder.CreateShl(part, shift);
6850+
partMask <<= shift;
6851+
}
6852+
6853+
// Truncate the output to the result size.
6854+
if (partMask.getBitWidth() > resultBitWidth) {
6855+
partMask = partMask.trunc(resultBitWidth);
6856+
part = builder.CreateTrunc(part, destTy);
6857+
}
6858+
6859+
// Mask out selected bits.
6860+
part = builder.CreateAnd(part, partMask);
68276861

68286862
// Accumulate the result.
6829-
if (result)
6830-
result = IGF.Builder.CreateOr(result, newBits);
6831-
else
6832-
result = newBits;
6863+
result = result ? builder.CreateOr(result, part) : part;
68336864

6834-
usedBits += numBits;
6865+
// Update the offset and remaining mask.
6866+
usedBits += partMask.countPopulation();
68356867
}
6868+
return result;
6869+
}
6870+
6871+
/// Unpack bits from the low bits of an integer value and
6872+
/// move them to the bit positions indicated by the mask.
6873+
/// Equivalent to a parallel bit deposit instruction (PDEP),
6874+
/// although we don't currently emit PDEP directly.
6875+
llvm::Value *irgen::emitScatterBits(IRGenFunction &IGF,
6876+
llvm::APInt mask,
6877+
llvm::Value *source,
6878+
unsigned packedLowBit) {
6879+
auto &builder = IGF.Builder;
6880+
auto &context = IGF.IGM.getLLVMContext();
6881+
6882+
// Expand the packed bits to the destination type.
6883+
auto destTy = llvm::IntegerType::get(context, mask.getBitWidth());
6884+
source = builder.CreateZExtOrTrunc(source, destTy);
6885+
6886+
// Shift each set of contiguous set bits into position and
6887+
// accumulate them into the result.
6888+
int64_t usedBits = packedLowBit;
6889+
llvm::Value *result = nullptr;
6890+
while (mask != 0) {
6891+
// Isolate the rightmost run of contiguous set bits.
6892+
// Example: 0b0011_01101_1100 -> 0b0000_0001_1100
6893+
llvm::APInt partMask = rightmostMask(mask);
6894+
6895+
// Update the bits we need to mask next.
6896+
mask ^= partMask;
68366897

6898+
// Shift the selected bits into position.
6899+
llvm::Value *part = source;
6900+
int64_t offset = int64_t(partMask.countTrailingZeros()) - usedBits;
6901+
if (offset > 0) {
6902+
part = builder.CreateShl(part, uint64_t(offset));
6903+
} else if (offset < 0) {
6904+
part = builder.CreateLShr(part, uint64_t(-offset));
6905+
}
6906+
6907+
// Mask out selected bits.
6908+
part = builder.CreateAnd(part, partMask);
6909+
6910+
// Accumulate the result.
6911+
result = result ? builder.CreateOr(result, part) : part;
6912+
6913+
// Update the offset and remaining mask.
6914+
usedBits += partMask.countPopulation();
6915+
}
68376916
return result;
68386917
}
68396918

@@ -6900,8 +6979,8 @@ EnumPayload irgen::interleaveSpareBits(IRGenFunction &IGF,
69006979
payloadValue = IGF.Builder.CreateLShr(payloadValue,
69016980
llvm::ConstantInt::get(IGF.IGM.Int32Ty, usedBits));
69026981
}
6903-
payloadValue = emitScatterSpareBits(IGF, spareBitsChunk,
6904-
payloadValue, 0);
6982+
payloadValue = emitScatterBits(IGF, spareBitsChunk.asAPInt(),
6983+
payloadValue, 0);
69056984
if (payloadValue->getType() != type) {
69066985
if (type->isPointerTy())
69076986
payloadValue = IGF.Builder.CreateIntToPtr(payloadValue, type);

trunk/lib/IRGen/GenEnum.h

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -103,17 +103,22 @@ EnumPayload interleaveSpareBits(IRGenFunction &IGF,
103103
const SpareBitVector &spareBitVector,
104104
llvm::Value *value);
105105

106-
/// Gather spare bits into the low bits of a smaller integer value.
107-
llvm::Value *emitGatherSpareBits(IRGenFunction &IGF,
108-
const SpareBitVector &spareBitMask,
109-
llvm::Value *spareBits,
110-
unsigned resultLowBit,
111-
unsigned resultBitWidth);
112-
/// Scatter spare bits from the low bits of a smaller integer value.
113-
llvm::Value *emitScatterSpareBits(IRGenFunction &IGF,
114-
const SpareBitVector &spareBitMask,
115-
llvm::Value *packedBits,
116-
unsigned packedLowBit);
106+
/// Pack masked bits into the low bits of an integer value.
107+
/// Equivalent to a parallel bit extract instruction (PEXT),
108+
/// although we don't currently emit PEXT directly.
109+
llvm::Value *emitGatherBits(IRGenFunction &IGF,
110+
llvm::APInt mask,
111+
llvm::Value *source,
112+
unsigned resultLowBit,
113+
unsigned resultBitWidth);
114+
/// Unpack bits from the low bits of an integer value and
115+
/// move them to the bit positions indicated by the mask.
116+
/// Equivalent to a parallel bit deposit instruction (PDEP),
117+
/// although we don't currently emit PDEP directly.
118+
llvm::Value *emitScatterBits(IRGenFunction &IGF,
119+
llvm::APInt mask,
120+
llvm::Value *packedBits,
121+
unsigned packedLowBit);
117122

118123
/// An implementation strategy for an enum, which handles how the enum is
119124
/// laid out and how to perform TypeInfo operations on values of the enum.

0 commit comments

Comments
 (0)