Skip to content

Try harder not to emit calls to swift_getExtendedExistentialTypeMetadata() [5.9] #65341

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions include/swift/SIL/SILType.h
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,12 @@ class SILType {
bool hasLocalArchetype() const {
return getASTType()->hasLocalArchetype();
}

/// Returns true if the referenced type is expressed in terms of one
/// or more parameterized protocol types.
bool hasParameterizedExistential() const {
return getASTType()->hasParameterizedExistential();
}

/// Returns the representation used by an existential type. If the concrete
/// type is provided, this may return a specialized representation kind that
Expand Down
105 changes: 16 additions & 89 deletions lib/IRGen/GenEnum.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -279,62 +279,6 @@ EnumImplStrategy::emitResilientTagIndices(IRGenModule &IGM) const {
}
}

void EnumImplStrategy::callOutlinedCopy(IRGenFunction &IGF,
Address dest, Address src, SILType T,
IsInitialization_t isInit,
IsTake_t isTake) const {
if (!IGF.IGM.getOptions().UseTypeLayoutValueHandling) {
OutliningMetadataCollector collector(IGF);
if (T.hasArchetype()) {
collectMetadataForOutlining(collector, T);
}
collector.emitCallToOutlinedCopy(dest, src, T, *TI, isInit, isTake);
return;
}

if (!T.hasArchetype()) {
// Call the outlined copy function (the implementation will call vwt in this
// case).
OutliningMetadataCollector collector(IGF);
collector.emitCallToOutlinedCopy(dest, src, T, *TI, isInit, isTake);
return;
}

if (isInit == IsInitialization && isTake == IsTake) {
return emitInitializeWithTakeCall(IGF, T, dest, src);
} else if (isInit == IsInitialization && isTake == IsNotTake) {
return emitInitializeWithCopyCall(IGF, T, dest, src);
} else if (isInit == IsNotInitialization && isTake == IsTake) {
return emitAssignWithTakeCall(IGF, T, dest, src);
} else if (isInit == IsNotInitialization && isTake == IsNotTake) {
return emitAssignWithCopyCall(IGF, T, dest, src);
}
llvm_unreachable("unknown case");
}

void EnumImplStrategy::callOutlinedDestroy(IRGenFunction &IGF,
Address addr, SILType T) const {
if (!IGF.IGM.getOptions().UseTypeLayoutValueHandling) {
OutliningMetadataCollector collector(IGF);
if (T.hasArchetype()) {
collectMetadataForOutlining(collector, T);
}
collector.emitCallToOutlinedDestroy(addr, T, *TI);
return;
}

if (!T.hasArchetype()) {
// Call the outlined copy function (the implementation will call vwt in this
// case).
OutliningMetadataCollector collector(IGF);
collector.emitCallToOutlinedDestroy(addr, T, *TI);
return;
}

emitDestroyCall(IGF, T, addr);
return;
}

namespace {
/// Implementation strategy for singleton enums, with zero or one cases.
class SingletonEnumImplStrategy final : public EnumImplStrategy {
Expand Down Expand Up @@ -549,7 +493,7 @@ namespace {
if (!getSingleton()) return;
if (!ElementsAreABIAccessible) {
emitAssignWithCopyCall(IGF, T, dest, src);
} else if (isOutlined || T.hasLocalArchetype()) {
} else if (isOutlined || T.hasParameterizedExistential()) {
dest = getSingletonAddress(IGF, dest);
src = getSingletonAddress(IGF, src);
getSingleton()->assignWithCopy(
Expand All @@ -564,7 +508,7 @@ namespace {
if (!getSingleton()) return;
if (!ElementsAreABIAccessible) {
emitAssignWithTakeCall(IGF, T, dest, src);
} else if (isOutlined || T.hasLocalArchetype()) {
} else if (isOutlined || T.hasParameterizedExistential()) {
dest = getSingletonAddress(IGF, dest);
src = getSingletonAddress(IGF, src);
getSingleton()->assignWithTake(
Expand All @@ -586,7 +530,7 @@ namespace {
if (!getSingleton()) return;
if (!ElementsAreABIAccessible) {
emitInitializeWithCopyCall(IGF, T, dest, src);
} else if (isOutlined || T.hasLocalArchetype()) {
} else if (isOutlined || T.hasParameterizedExistential()) {
dest = getSingletonAddress(IGF, dest);
src = getSingletonAddress(IGF, src);
getSingleton()->initializeWithCopy(
Expand All @@ -601,7 +545,7 @@ namespace {
if (!getSingleton()) return;
if (!ElementsAreABIAccessible) {
emitInitializeWithTakeCall(IGF, T, dest, src);
} else if (isOutlined || T.hasLocalArchetype()) {
} else if (isOutlined || T.hasParameterizedExistential()) {
dest = getSingletonAddress(IGF, dest);
src = getSingletonAddress(IGF, src);
getSingleton()->initializeWithTake(
Expand Down Expand Up @@ -657,7 +601,7 @@ namespace {
!getSingleton()->isTriviallyDestroyable(ResilienceExpansion::Maximal)) {
if (!ElementsAreABIAccessible) {
emitDestroyCall(IGF, T, addr);
} else if (isOutlined || T.hasLocalArchetype()) {
} else if (isOutlined || T.hasParameterizedExistential()) {
getSingleton()->destroy(IGF, getSingletonAddress(IGF, addr),
getSingletonType(IGF.IGM, T), isOutlined);
} else {
Expand Down Expand Up @@ -2810,7 +2754,7 @@ namespace {
}
if (!ElementsAreABIAccessible) {
return emitDestroyCall(IGF, T, addr);
} else if (isOutlined || T.hasLocalArchetype()) {
} else if (isOutlined || T.hasParameterizedExistential()) {
switch (CopyDestroyKind) {
case TriviallyDestroyable:
return;
Expand Down Expand Up @@ -2854,24 +2798,7 @@ namespace {
}
}
} else {
if (!IGF.IGM.getOptions().UseTypeLayoutValueHandling) {
OutliningMetadataCollector collector(IGF);
if (T.hasArchetype()) {
collectMetadataForOutlining(collector, T);
}
collector.emitCallToOutlinedDestroy(addr, T, *TI);
return;
}

if (!T.hasArchetype()) {
// Call the outlined copy function (the implementation will call vwt
// in this case).
OutliningMetadataCollector collector(IGF);
collector.emitCallToOutlinedDestroy(addr, T, *TI);
return;
}

emitDestroyCall(IGF, T, addr);
callOutlinedDestroy(IGF, addr, T);
return;
}
}
Expand Down Expand Up @@ -3114,7 +3041,7 @@ namespace {
SILType T, bool isOutlined) const override {
if (!ElementsAreABIAccessible) {
emitAssignWithCopyCall(IGF, T, dest, src);
} else if (isOutlined || T.hasLocalArchetype()) {
} else if (isOutlined || T.hasParameterizedExistential()) {
emitIndirectAssign(IGF, dest, src, T, IsNotTake, isOutlined);
} else {
callOutlinedCopy(IGF, dest, src, T, IsNotInitialization, IsNotTake);
Expand All @@ -3125,7 +3052,7 @@ namespace {
SILType T, bool isOutlined) const override {
if (!ElementsAreABIAccessible) {
emitAssignWithTakeCall(IGF, T, dest, src);
} else if (isOutlined || T.hasLocalArchetype()) {
} else if (isOutlined || T.hasParameterizedExistential()) {
emitIndirectAssign(IGF, dest, src, T, IsTake, isOutlined);
} else {
callOutlinedCopy(IGF, dest, src, T, IsNotInitialization, IsTake);
Expand All @@ -3136,7 +3063,7 @@ namespace {
SILType T, bool isOutlined) const override {
if (!ElementsAreABIAccessible) {
emitInitializeWithCopyCall(IGF, T, dest, src);
} else if (isOutlined || T.hasLocalArchetype()) {
} else if (isOutlined || T.hasParameterizedExistential()) {
emitIndirectInitialize(IGF, dest, src, T, IsNotTake, isOutlined);
} else {
callOutlinedCopy(IGF, dest, src, T, IsInitialization, IsNotTake);
Expand All @@ -3147,7 +3074,7 @@ namespace {
SILType T, bool isOutlined) const override {
if (!ElementsAreABIAccessible) {
emitInitializeWithTakeCall(IGF, T, dest, src);
} else if (isOutlined || T.hasLocalArchetype()) {
} else if (isOutlined || T.hasParameterizedExistential()) {
emitIndirectInitialize(IGF, dest, src, T, IsTake, isOutlined);
} else {
callOutlinedCopy(IGF, dest, src, T, IsInitialization, IsTake);
Expand Down Expand Up @@ -4972,7 +4899,7 @@ namespace {
SILType T, bool isOutlined) const override {
if (!ElementsAreABIAccessible) {
emitAssignWithCopyCall(IGF, T, dest, src);
} else if (isOutlined || T.hasLocalArchetype()) {
} else if (isOutlined || T.hasParameterizedExistential()) {
emitIndirectAssign(IGF, dest, src, T, IsNotTake, isOutlined);
} else {
callOutlinedCopy(IGF, dest, src, T, IsNotInitialization, IsNotTake);
Expand All @@ -4983,7 +4910,7 @@ namespace {
SILType T, bool isOutlined) const override {
if (!ElementsAreABIAccessible) {
emitAssignWithTakeCall(IGF, T, dest, src);
} else if (isOutlined || T.hasLocalArchetype()) {
} else if (isOutlined || T.hasParameterizedExistential()) {
emitIndirectAssign(IGF, dest, src, T, IsTake, isOutlined);
} else {
callOutlinedCopy(IGF, dest, src, T, IsNotInitialization, IsTake);
Expand All @@ -4994,7 +4921,7 @@ namespace {
SILType T, bool isOutlined) const override {
if (!ElementsAreABIAccessible) {
emitInitializeWithCopyCall(IGF, T, dest, src);
} else if (isOutlined || T.hasLocalArchetype()) {
} else if (isOutlined || T.hasParameterizedExistential()) {
emitIndirectInitialize(IGF, dest, src, T, IsNotTake, isOutlined);
} else {
callOutlinedCopy(IGF, dest, src, T, IsInitialization, IsNotTake);
Expand All @@ -5005,7 +4932,7 @@ namespace {
SILType T, bool isOutlined) const override {
if (!ElementsAreABIAccessible) {
emitInitializeWithTakeCall(IGF, T, dest, src);
} else if (isOutlined || T.hasLocalArchetype()) {
} else if (isOutlined || T.hasParameterizedExistential()) {
emitIndirectInitialize(IGF, dest, src, T, IsTake, isOutlined);
} else {
callOutlinedCopy(IGF, dest, src, T, IsInitialization, IsTake);
Expand Down Expand Up @@ -5039,7 +4966,7 @@ namespace {
}
if (!ElementsAreABIAccessible) {
emitDestroyCall(IGF, T, addr);
} else if (isOutlined || T.hasLocalArchetype()) {
} else if (isOutlined || T.hasParameterizedExistential()) {
switch (CopyDestroyKind) {
case TriviallyDestroyable:
return;
Expand Down
8 changes: 6 additions & 2 deletions lib/IRGen/GenEnum.h
Original file line number Diff line number Diff line change
Expand Up @@ -449,9 +449,13 @@ class EnumImplStrategy {

void callOutlinedCopy(IRGenFunction &IGF, Address dest, Address src,
SILType T, IsInitialization_t isInit,
IsTake_t isTake) const;
IsTake_t isTake) const {
TI->callOutlinedCopy(IGF, dest, src, T, isInit, isTake);
}

void callOutlinedDestroy(IRGenFunction &IGF, Address addr, SILType T) const;
void callOutlinedDestroy(IRGenFunction &IGF, Address addr, SILType T) const {
TI->callOutlinedDestroy(IGF, addr, T);
}

virtual void collectMetadataForOutlining(OutliningMetadataCollector &collector,
SILType T) const = 0;
Expand Down
10 changes: 5 additions & 5 deletions lib/IRGen/GenRecord.h
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ class RecordTypeInfoImpl : public Base,
return emitAssignWithCopyCall(IGF, T, dest, src);
}

if (isOutlined || T.hasLocalArchetype()) {
if (isOutlined || T.hasParameterizedExistential()) {
auto offsets = asImpl().getNonFixedOffsets(IGF, T);
for (auto &field : getFields()) {
if (field.isEmpty())
Expand All @@ -193,7 +193,7 @@ class RecordTypeInfoImpl : public Base,
return emitAssignWithTakeCall(IGF, T, dest, src);
}

if (isOutlined || T.hasLocalArchetype()) {
if (isOutlined || T.hasParameterizedExistential()) {
auto offsets = asImpl().getNonFixedOffsets(IGF, T);
for (auto &field : getFields()) {
if (field.isEmpty())
Expand Down Expand Up @@ -223,7 +223,7 @@ class RecordTypeInfoImpl : public Base,
return emitInitializeWithCopyCall(IGF, T, dest, src);
}

if (isOutlined || T.hasLocalArchetype()) {
if (isOutlined || T.hasParameterizedExistential()) {
auto offsets = asImpl().getNonFixedOffsets(IGF, T);
for (auto &field : getFields()) {
if (field.isEmpty())
Expand Down Expand Up @@ -255,7 +255,7 @@ class RecordTypeInfoImpl : public Base,
return emitInitializeWithTakeCall(IGF, T, dest, src);
}

if (isOutlined || T.hasLocalArchetype()) {
if (isOutlined || T.hasParameterizedExistential()) {
auto offsets = asImpl().getNonFixedOffsets(IGF, T);
for (auto &field : getFields()) {
if (field.isEmpty())
Expand All @@ -278,7 +278,7 @@ class RecordTypeInfoImpl : public Base,
return emitDestroyCall(IGF, T, addr);
}

if (isOutlined || T.hasLocalArchetype()) {
if (isOutlined || T.hasParameterizedExistential()) {
auto offsets = asImpl().getNonFixedOffsets(IGF, T);
for (auto &field : getFields()) {
if (field.isTriviallyDestroyable())
Expand Down
6 changes: 4 additions & 2 deletions lib/IRGen/Outlining.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,8 @@ irgen::getTypeAndGenericSignatureForManglingOutlineFunction(SILType type) {
void TypeInfo::callOutlinedCopy(IRGenFunction &IGF, Address dest, Address src,
SILType T, IsInitialization_t isInit,
IsTake_t isTake) const {
if (!IGF.IGM.getOptions().UseTypeLayoutValueHandling) {
if (!T.hasLocalArchetype() &&
!IGF.IGM.getOptions().UseTypeLayoutValueHandling) {
OutliningMetadataCollector collector(IGF);
if (T.hasArchetype()) {
collectMetadataForOutlining(collector, T);
Expand Down Expand Up @@ -340,7 +341,8 @@ void TypeInfo::callOutlinedDestroy(IRGenFunction &IGF,
if (IGF.IGM.getTypeLowering(T).isTrivial())
return;

if (!IGF.IGM.getOptions().UseTypeLayoutValueHandling) {
if (!T.hasLocalArchetype() &&
!IGF.IGM.getOptions().UseTypeLayoutValueHandling) {
OutliningMetadataCollector collector(IGF);
if (T.hasArchetype()) {
collectMetadataForOutlining(collector, T);
Expand Down
22 changes: 22 additions & 0 deletions test/IRGen/extended_existential_metadata.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// RUN: %target-swift-frontend -emit-ir %s | %FileCheck %s
// RUN: %target-swift-frontend -emit-ir -O %s | %FileCheck %s

protocol Foo<T> {
associatedtype T
func acceptEvent<T>(event: T)
}

protocol FooFactory<T> {
associatedtype T
func makeFoo() -> any Foo<T>
}

class Bar<T> {
private var foo: (any Foo<T>)

init(fooFactory: any FooFactory<T>) {
self.foo = fooFactory.makeFoo()
}
}

// CHECK-NOT: swift_getExtendedExistentialTypeMetadata
4 changes: 3 additions & 1 deletion test/IRGen/variadic_generic_outlining.sil
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@ struct Wrapper<Value> {
// CHECK-NEXT: [[PACK:%.*]] = inttoptr [[INT]] [[PACK_ADDR2]] to %swift.type**
// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[PACK]], [[INT]]
// CHECK-NEXT: [[ELT_TYPE:%.*]] = load %swift.type*, %swift.type** [[T0]], align
// CHECK: [[WRAPPER_RESPONSE:%.*]] = call swiftcc %swift.metadata_response @"$s26variadic_generic_outlining7WrapperVMa"
// CHECK-NEXT: [[WRAPPER_TYPE:%.*]] = extractvalue %swift.metadata_response [[WRAPPER_RESPONSE]]
// Test that we do the copy through the VWT for the element type.
// CHECK: [[T0:%.*]] = bitcast %swift.type* [[ELT_TYPE]] to i8***
// CHECK-NEXT: [[T0:%.*]] = bitcast %swift.type* [[WRAPPER_TYPE]] to i8***
// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8**, i8*** [[T0]], [[INT]] -1
sil hidden @test_outlining : $@convention(thin) <each T> (@pack_guaranteed Pack{repeat Wrapper<each T>}) -> @pack_out Pack{repeat Wrapper<each T>} {
bb0(%0 : $*Pack{repeat Wrapper<each T>}, %1 : $*Pack{repeat Wrapper<each T>}):
Expand Down