Skip to content

Commit 381cf59

Browse files
authored
Merge pull request #24978 from linux-on-ibm-z/interleave
[IRGen] Simplify constant occupied/spare bit interleaving
2 parents 3033a72 + 253d5b5 commit 381cf59

File tree

3 files changed

+27
-54
lines changed

3 files changed

+27
-54
lines changed

lib/IRGen/GenEnum.cpp

Lines changed: 17 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -3575,12 +3575,8 @@ namespace {
35753575
if (CommonSpareBits.empty())
35763576
return APInt();
35773577

3578-
APInt v = interleaveSpareBits(IGM, PayloadTagBits,
3579-
PayloadTagBits.size(),
3580-
tag, 0);
3581-
v |= interleaveSpareBits(IGM, CommonSpareBits,
3582-
CommonSpareBits.size(),
3583-
0, tagIndex);
3578+
APInt v = scatterBits(PayloadTagBits.asAPInt(), tag);
3579+
v |= scatterBits(~CommonSpareBits.asAPInt(), tagIndex);
35843580
return v;
35853581
}
35863582

@@ -4125,9 +4121,7 @@ namespace {
41254121
// If we have spare bits, pack tag bits into them.
41264122
unsigned numSpareBits = PayloadTagBits.count();
41274123
if (numSpareBits > 0) {
4128-
APInt tagMaskVal
4129-
= interleaveSpareBits(IGM, PayloadTagBits,
4130-
PayloadTagBits.size(), tag, 0);
4124+
APInt tagMaskVal = scatterBits(PayloadTagBits.asAPInt(), tag);
41314125
payload.emitApplyOrMask(IGF, tagMaskVal);
41324126
}
41334127

@@ -4801,9 +4795,7 @@ namespace {
48014795
// enum containing this enum as a payload. Single payload layout
48024796
// unfortunately assumes that tagging the payload case is a no-op.
48034797
auto spareBitMask = ~CommonSpareBits.asAPInt();
4804-
APInt tagBitMask
4805-
= interleaveSpareBits(IGM, PayloadTagBits, PayloadTagBits.size(),
4806-
spareTagBits, 0);
4798+
APInt tagBitMask = scatterBits(PayloadTagBits.asAPInt(), spareTagBits);
48074799

48084800
payload.emitApplyAndMask(IGF, spareBitMask);
48094801
payload.emitApplyOrMask(IGF, tagBitMask);
@@ -5315,8 +5307,8 @@ namespace {
53155307
auto payloadTagMask = payloadBitCount >= 32
53165308
? ~0u : (1 << payloadBitCount) - 1;
53175309
auto payloadPart = mask & payloadTagMask;
5318-
auto payloadBits = interleaveSpareBits(IGM, CommonSpareBits,
5319-
bits, payloadPart, 0);
5310+
auto payloadBits = scatterBits(CommonSpareBits.asAPInt().zextOrTrunc(bits),
5311+
payloadPart);
53205312
if (getExtraTagBitCountForExtraInhabitants() > 0) {
53215313
auto extraBits = APInt(bits,
53225314
(mask >> payloadBitCount) & extraTagMask)
@@ -6916,41 +6908,20 @@ llvm::Value *irgen::emitScatterBits(IRGenFunction &IGF,
69166908
return result;
69176909
}
69186910

6919-
/// Interleave the occupiedValue and spareValue bits, taking a bit from one
6920-
/// or the other at each position based on the spareBits mask.
6921-
APInt
6922-
irgen::interleaveSpareBits(IRGenModule &IGM, const SpareBitVector &spareBits,
6923-
unsigned bits,
6924-
unsigned spareValue, unsigned occupiedValue) {
6925-
// FIXME: endianness.
6926-
SmallVector<llvm::APInt::WordType, 2> valueParts;
6927-
valueParts.push_back(0);
6928-
6929-
llvm::APInt::WordType valueBit = 1;
6930-
auto advanceValueBit = [&]{
6931-
valueBit <<= 1;
6932-
if (valueBit == 0) {
6933-
valueParts.push_back(0);
6934-
valueBit = 1;
6911+
/// Unpack bits from the low bits of an integer value and
6912+
/// move them to the bit positions indicated by the mask.
6913+
llvm::APInt irgen::scatterBits(const llvm::APInt &mask, unsigned value) {
6914+
llvm::APInt result(mask.getBitWidth(), 0);
6915+
for (unsigned i = 0; i < mask.getBitWidth() && value != 0; ++i) {
6916+
if (!mask[i]) {
6917+
continue;
69356918
}
6936-
};
6937-
6938-
for (unsigned i = 0, e = spareBits.size();
6939-
(occupiedValue || spareValue) && i < e;
6940-
++i, advanceValueBit()) {
6941-
if (spareBits[i]) {
6942-
if (spareValue & 1)
6943-
valueParts.back() |= valueBit;
6944-
spareValue >>= 1;
6945-
} else {
6946-
if (occupiedValue & 1)
6947-
valueParts.back() |= valueBit;
6948-
occupiedValue >>= 1;
6919+
if (value & 1) {
6920+
result.setBit(i);
69496921
}
6922+
value >>= 1;
69506923
}
6951-
6952-
// Create the value.
6953-
return llvm::APInt(bits, valueParts);
6924+
return result;
69546925
}
69556926

69566927
/// A version of the above where the tag value is dynamic.

lib/IRGen/GenEnum.h

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -91,13 +91,7 @@ void emitStoreEnumTagToAddress(IRGenFunction &IGF,
9191
Address enumAddr,
9292
EnumElementDecl *theCase);
9393

94-
/// Interleave the occupiedValue and spareValue bits, taking a bit from one
95-
/// or the other at each position based on the spareBits mask.
96-
APInt
97-
interleaveSpareBits(IRGenModule &IGM, const SpareBitVector &spareBits,
98-
unsigned bits, unsigned spareValue, unsigned occupiedValue);
99-
100-
/// A version of the above where the tag value is dynamic.
94+
/// Unpack bits from value and scatter them into the masked bits.
10195
EnumPayload interleaveSpareBits(IRGenFunction &IGF,
10296
const EnumPayloadSchema &schema,
10397
const SpareBitVector &spareBitVector,
@@ -111,6 +105,7 @@ llvm::Value *emitGatherBits(IRGenFunction &IGF,
111105
llvm::Value *source,
112106
unsigned resultLowBit,
113107
unsigned resultBitWidth);
108+
114109
/// Unpack bits from the low bits of an integer value and
115110
/// move them to the bit positions indicated by the mask.
116111
/// Equivalent to a parallel bit deposit instruction (PDEP),
@@ -119,6 +114,10 @@ llvm::Value *emitScatterBits(IRGenFunction &IGF,
119114
llvm::APInt mask,
120115
llvm::Value *packedBits,
121116
unsigned packedLowBit);
117+
118+
/// Unpack bits from the low bits of an integer value and
119+
/// move them to the bit positions indicated by the mask.
120+
llvm::APInt scatterBits(const llvm::APInt &mask, unsigned value);
122121

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

lib/IRGen/GenType.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,10 @@ FixedTypeInfo::getSpareBitFixedExtraInhabitantValue(IRGenModule &IGM,
294294
spareIndex = (index >> occupiedBitCount) + 1;
295295
}
296296

297-
return interleaveSpareBits(IGM, SpareBits, bits, spareIndex, occupiedIndex);
297+
APInt mask = SpareBits.asAPInt().zextOrTrunc(bits);
298+
APInt v = scatterBits(mask, spareIndex);
299+
v |= scatterBits(~mask, occupiedIndex);
300+
return v;
298301
}
299302

300303
llvm::Value *

0 commit comments

Comments
 (0)