mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Use the first element of structs and tuples as a source
for extra inhabitants. For structs in particular, this eliminates a major source of abstraction penatlies. For example, an optional struct containing an object pointer is now represented the same way as an optional object pointer, which is critical for correctly importing CF types as Unmanaged<T>!. In time, we should generalize this to consider all elements as sources for extra inhabitants, as well as exploiting spare bits in the representation, but getting the single-element case right really provides the bulk of the benefit. This commit restores r17242 and r17243 with a fix to use value witnesses that actually forward the right type metadata down. We were already generating these value witnesses in the dependent struct VWT pattern, but I was being too clever and trying to use the underlying value witness directly. Swift SVN r17267
This commit is contained in:
@@ -379,7 +379,8 @@ namespace {
|
||||
}
|
||||
|
||||
return getSingleton()->getExtraInhabitantIndex(IGF,
|
||||
getSingletonAddress(IGF, src), T);
|
||||
getSingletonAddress(IGF, src),
|
||||
getSingletonType(IGF.IGM, T));
|
||||
}
|
||||
|
||||
void storeExtraInhabitant(IRGenFunction &IGF,
|
||||
@@ -390,7 +391,8 @@ namespace {
|
||||
return;
|
||||
}
|
||||
getSingleton()->storeExtraInhabitant(IGF, index,
|
||||
getSingletonAddress(IGF, dest), T);
|
||||
getSingletonAddress(IGF, dest),
|
||||
getSingletonType(IGF.IGM, T));
|
||||
}
|
||||
|
||||
unsigned getFixedExtraInhabitantCount(IRGenModule &IGM) const override {
|
||||
@@ -998,6 +1000,8 @@ namespace {
|
||||
};
|
||||
|
||||
CopyDestroyStrategy CopyDestroyKind;
|
||||
|
||||
unsigned NumExtraInhabitantTagValues = ~0U;
|
||||
|
||||
public:
|
||||
SinglePayloadEnumImplStrategy(IRGenModule &IGM,
|
||||
@@ -1036,6 +1040,13 @@ namespace {
|
||||
|
||||
// TODO: Same for single unknown-refcounted pointers.
|
||||
}
|
||||
|
||||
/// Return the number of tag values represented with extra
|
||||
/// inhabitants in the payload.
|
||||
unsigned getNumExtraInhabitantTagValues() const {
|
||||
assert(NumExtraInhabitantTagValues != ~0U);
|
||||
return NumExtraInhabitantTagValues;
|
||||
}
|
||||
|
||||
/// The payload for a single-payload enum is always placed in front and
|
||||
/// will never have interleaved tag bits, so we can just bitcast the enum
|
||||
@@ -1137,8 +1148,7 @@ namespace {
|
||||
if (payloadTy)
|
||||
payload = value.claimNext();
|
||||
llvm::BasicBlock *payloadDest = blockForCase(getPayloadElement());
|
||||
unsigned extraInhabitantCount
|
||||
= getFixedPayloadTypeInfo().getFixedExtraInhabitantCount(IGF.IGM);
|
||||
unsigned extraInhabitantCount = getNumExtraInhabitantTagValues();
|
||||
|
||||
// If there are extra tag bits, switch over them first.
|
||||
SmallVector<llvm::BasicBlock*, 2> tagBitBlocks;
|
||||
@@ -1193,7 +1203,9 @@ namespace {
|
||||
= getFixedPayloadTypeInfo().getFixedSize().getValueInBits();
|
||||
if (extraInhabitantCount > 0) {
|
||||
assert(payload && "extra inhabitants with empty payload?!");
|
||||
auto *swi = IGF.Builder.CreateSwitch(payload, payloadDest);
|
||||
auto *switchValue =
|
||||
getFixedPayloadTypeInfo().maskFixedExtraInhabitant(IGF, payload);
|
||||
auto *swi = IGF.Builder.CreateSwitch(switchValue, payloadDest);
|
||||
for (unsigned i = 0; i < extraInhabitantCount && elti != eltEnd; ++i) {
|
||||
auto v = getFixedPayloadTypeInfo().getFixedExtraInhabitantValue(
|
||||
IGF.IGM, payloadBits, i);
|
||||
@@ -1363,8 +1375,7 @@ namespace {
|
||||
// Non-payload cases use extra inhabitants, if any, or are discriminated
|
||||
// by setting the tag bits.
|
||||
unsigned tagIndex = getSimpleElementTagIndex(elt);
|
||||
unsigned numExtraInhabitants
|
||||
= getFixedPayloadTypeInfo().getFixedExtraInhabitantCount(IGM);
|
||||
unsigned numExtraInhabitants = getNumExtraInhabitantTagValues();
|
||||
llvm::ConstantInt *payload = nullptr;
|
||||
unsigned extraTagValue;
|
||||
if (tagIndex < numExtraInhabitants) {
|
||||
@@ -1465,11 +1476,15 @@ namespace {
|
||||
|
||||
// If we used extra inhabitants to represent empty case discriminators,
|
||||
// weed them out.
|
||||
unsigned numExtraInhabitants
|
||||
= getFixedPayloadTypeInfo().getFixedExtraInhabitantCount(IGF.IGM);
|
||||
unsigned numExtraInhabitants = getNumExtraInhabitantTagValues();
|
||||
if (numExtraInhabitants > 0) {
|
||||
unsigned bitWidth =
|
||||
getFixedPayloadTypeInfo().getFixedSize().getValueInBits();
|
||||
|
||||
auto *payloadBB = llvm::BasicBlock::Create(IGF.IGM.getLLVMContext());
|
||||
auto *swi = IGF.Builder.CreateSwitch(payload, payloadBB);
|
||||
auto *switchValue =
|
||||
getFixedPayloadTypeInfo().maskFixedExtraInhabitant(IGF, payload);
|
||||
auto *swi = IGF.Builder.CreateSwitch(switchValue, payloadBB);
|
||||
|
||||
auto elements = getPayloadElement()->getParentEnum()->getAllElements();
|
||||
unsigned inhabitant = 0;
|
||||
@@ -1482,9 +1497,7 @@ namespace {
|
||||
break;
|
||||
}
|
||||
auto xi = getFixedPayloadTypeInfo().getFixedExtraInhabitantValue(
|
||||
IGF.IGM,
|
||||
getFixedPayloadTypeInfo().getFixedSize().getValueInBits(),
|
||||
inhabitant);
|
||||
IGF.IGM, bitWidth, inhabitant);
|
||||
swi->addCase(xi, falseBB);
|
||||
}
|
||||
|
||||
@@ -2001,15 +2014,8 @@ namespace {
|
||||
}
|
||||
|
||||
unsigned getFixedExtraInhabitantCount(IRGenModule &IGM) const override {
|
||||
unsigned payloadXI
|
||||
= getFixedPayloadTypeInfo().getFixedExtraInhabitantCount(IGM);
|
||||
|
||||
unsigned numEmptyCases = ElementsWithNoPayload.size();
|
||||
|
||||
if (payloadXI <= numEmptyCases)
|
||||
return 0;
|
||||
|
||||
return payloadXI - numEmptyCases;
|
||||
return getFixedPayloadTypeInfo().getFixedExtraInhabitantCount(IGM)
|
||||
- getNumExtraInhabitantTagValues();
|
||||
}
|
||||
|
||||
llvm::ConstantInt *
|
||||
@@ -2018,7 +2024,7 @@ namespace {
|
||||
unsigned index) const override {
|
||||
return getFixedPayloadTypeInfo()
|
||||
.getFixedExtraInhabitantValue(IGM, bits,
|
||||
index + ElementsWithNoPayload.size());
|
||||
index + getNumExtraInhabitantTagValues());
|
||||
}
|
||||
|
||||
llvm::Value *
|
||||
@@ -3550,9 +3556,9 @@ namespace {
|
||||
// Determine how many tag bits we need. Given N extra inhabitants, we
|
||||
// represent the first N tags using those inhabitants. For additional tags,
|
||||
// we use discriminator bit(s) to inhabit the full bit size of the payload.
|
||||
unsigned tagsWithoutInhabitants = numTags <= fixedExtraInhabitants
|
||||
? 0 : numTags - fixedExtraInhabitants;
|
||||
NumExtraInhabitantTagValues = std::min(numTags, fixedExtraInhabitants);
|
||||
|
||||
unsigned tagsWithoutInhabitants = numTags - NumExtraInhabitantTagValues;
|
||||
if (tagsWithoutInhabitants == 0) {
|
||||
ExtraTagBitCount = 0;
|
||||
NumExtraTagValues = 0;
|
||||
|
||||
Reference in New Issue
Block a user