Skip to content

Commit 4a97914

Browse files
Merge pull request #29488 from nate-chandler/generic-metadata-prespecialization-components/default-on
[metadata prespecialization] On by default.
2 parents a014248 + ae1f41e commit 4a97914

File tree

55 files changed

+2115
-98
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+2115
-98
lines changed

include/swift/AST/IRGenOptions.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ class IRGenOptions {
262262
EnableAnonymousContextMangledNames(false), ForcePublicLinkage(false),
263263
LazyInitializeClassMetadata(false),
264264
LazyInitializeProtocolConformances(false), DisableLegacyTypeInfo(false),
265-
PrespecializeGenericMetadata(false), UseIncrementalLLVMCodeGen(true),
265+
PrespecializeGenericMetadata(true), UseIncrementalLLVMCodeGen(true),
266266
UseSwiftCall(false), GenerateProfile(false),
267267
EnableDynamicReplacementChaining(false),
268268
DisableRoundTripDebugTypes(false), DisableDebuggerShadowCopies(false),

include/swift/Option/FrontendOptions.td

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -651,9 +651,9 @@ def disable_verify_exclusivity : Flag<["-"], "disable-verify-exclusivity">,
651651
def disable_legacy_type_info : Flag<["-"], "disable-legacy-type-info">,
652652
HelpText<"Completely disable legacy type layout">;
653653

654-
def prespecialize_generic_metadata : Flag<["-"], "prespecialize-generic-metadata">,
655-
HelpText<"Statically specialize metadata for generic types at types that "
656-
"are known to be used in source.">;
654+
def disable_generic_metadata_prespecialization : Flag<["-"], "disable-generic-metadata-prespecialization">,
655+
HelpText<"Do not statically specialize metadata for generic types at types "
656+
"that are known to be used in source.">;
657657

658658
def read_legacy_type_info_path_EQ : Joined<["-"], "read-legacy-type-info-path=">,
659659
HelpText<"Read legacy type layout from the given path instead of default path">;

lib/Frontend/CompilerInvocation.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1338,8 +1338,8 @@ static bool ParseIRGenArgs(IRGenOptions &Opts, ArgList &Args,
13381338
Opts.DisableLegacyTypeInfo = true;
13391339
}
13401340

1341-
if (Args.hasArg(OPT_prespecialize_generic_metadata)) {
1342-
Opts.PrespecializeGenericMetadata = true;
1341+
if (Args.hasArg(OPT_disable_generic_metadata_prespecialization)) {
1342+
Opts.PrespecializeGenericMetadata = false;
13431343
}
13441344

13451345
if (const Arg *A = Args.getLastArg(OPT_read_legacy_type_info_path_EQ)) {

lib/IRGen/IRGenModule.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1340,7 +1340,8 @@ bool IRGenModule::shouldPrespecializeGenericMetadata() {
13401340
AvailabilityContext::forDeploymentTarget(context);
13411341
return IRGen.Opts.PrespecializeGenericMetadata &&
13421342
deploymentAvailability.isContainedIn(
1343-
context.getPrespecializedGenericMetadataAvailability());
1343+
context.getPrespecializedGenericMetadataAvailability()) &&
1344+
(Triple.isOSDarwin() || Triple.isTvOS() || Triple.isOSLinux());
13441345
}
13451346

13461347
void IRGenerator::addGenModule(SourceFile *SF, IRGenModule *IGM) {

lib/IRGen/MetadataRequest.cpp

Lines changed: 47 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -701,36 +701,40 @@ bool irgen::isNominalGenericContextTypeMetadataAccessTrivial(
701701
auto substitutions =
702702
type->getContextSubstitutionMap(IGM.getSwiftModule(), &nominal);
703703

704-
return llvm::all_of(environment->getGenericParams(), [&](auto parameter) {
705-
auto conformances =
706-
environment->getGenericSignature()->getConformsTo(parameter);
707-
auto witnessTablesAreReferenceable =
708-
llvm::all_of(conformances, [&](ProtocolDecl *conformance) {
709-
return conformance->getModuleContext() == IGM.getSwiftModule() &&
710-
!conformance->isResilient(IGM.getSwiftModule(),
711-
ResilienceExpansion::Minimal);
712-
});
704+
auto allWitnessTablesAreReferenceable = llvm::all_of(environment->getGenericParams(), [&](auto parameter) {
705+
auto signature = environment->getGenericSignature();
706+
auto protocols = signature->getConformsTo(parameter);
713707
auto argument = ((Type *)parameter)->subst(substitutions);
714-
auto genericArgument = argument->getAnyGeneric();
715-
// For now, to avoid statically specializing generic protocol witness
716-
// tables, don't statically specialize metadata for types any of whose
717-
// arguments are generic.
718-
//
719-
// TODO: This is more pessimistic than necessary. Specialize even in
720-
// the face of generic arguments so long as those arguments
721-
// aren't required to conform to any protocols.
722-
//
708+
auto canonicalType = argument->getCanonicalType();
709+
auto witnessTablesAreReferenceable = [&]() {
710+
return llvm::all_of(protocols, [&](ProtocolDecl *protocol) {
711+
auto conformance =
712+
signature->lookupConformance(canonicalType, protocol);
713+
if (!conformance.isConcrete()) {
714+
return false;
715+
}
716+
auto rootConformance = conformance.getConcrete()->getRootConformance();
717+
return !IGM.isDependentConformance(rootConformance) &&
718+
!IGM.isResilientConformance(rootConformance);
719+
});
720+
};
723721
// TODO: Once witness tables are statically specialized, check whether the
724722
// ConformanceInfo returns nullptr from tryGetConstantTable.
725-
// early return.
726-
auto isGeneric = genericArgument && genericArgument->isGenericContext();
727-
auto isNominal = argument->getNominalOrBoundGenericNominal();
728-
auto isExistential = argument->isExistentialType();
729-
return isNominal && !isGeneric && !isExistential &&
730-
witnessTablesAreReferenceable &&
731-
irgen::isTypeMetadataAccessTrivial(IGM,
732-
argument->getCanonicalType());
733-
}) && IGM.getTypeInfoForUnlowered(type).isFixedSize(ResilienceExpansion::Maximal);
723+
auto isGenericWithoutPrespecializedConformance = [&]() {
724+
auto genericArgument = argument->getAnyGeneric();
725+
return genericArgument && genericArgument->isGenericContext() &&
726+
(protocols.size() > 0);
727+
};
728+
auto isExistential = [&]() { return argument->isExistentialType(); };
729+
auto metadataAccessIsTrivial = [&]() {
730+
return irgen::isTypeMetadataAccessTrivial(IGM,
731+
argument->getCanonicalType());
732+
};
733+
return !isGenericWithoutPrespecializedConformance() && !isExistential() &&
734+
metadataAccessIsTrivial() && witnessTablesAreReferenceable();
735+
});
736+
return allWitnessTablesAreReferenceable
737+
&& IGM.getTypeInfoForUnlowered(type).isFixedSize(ResilienceExpansion::Maximal);
734738
}
735739

736740
/// Is it basically trivial to access the given metadata? If so, we don't
@@ -1753,28 +1757,33 @@ static void emitCanonicalSpecializationsForGenericTypeMetadataAccessFunction(
17531757
SmallVector<std::pair<llvm::BasicBlock *, llvm::Value *>, 4>
17541758
specializationBlocks;
17551759
auto switchDestination = llvm::BasicBlock::Create(IGM.getLLVMContext());
1756-
unsigned long index = 0;
1760+
unsigned long blockIndex = 0;
17571761
for (auto specialization : specializations) {
1758-
auto conditionBlock = conditionBlocks[index];
1762+
auto conditionBlock = conditionBlocks[blockIndex];
17591763
IGF.Builder.emitBlock(conditionBlock);
1760-
auto successorBlock = index < conditionBlocks.size() - 1
1761-
? conditionBlocks[index + 1]
1764+
auto successorBlock = blockIndex < conditionBlocks.size() - 1
1765+
? conditionBlocks[blockIndex + 1]
17621766
: switchDestination;
17631767
auto specializationBlock = llvm::BasicBlock::Create(IGM.getLLVMContext());
17641768
auto substitutions = specialization->getContextSubstitutionMap(
17651769
IGM.getSwiftModule(), nominal);
17661770

17671771
llvm::Value *condition = llvm::ConstantInt::get(IGM.Int1Ty, 1);
1768-
auto generic = specialization->getAnyGeneric();
1769-
auto parameters = generic->getGenericEnvironment()->getGenericParams();
1770-
for (size_t index = 0; index < parameters.size(); ++index) {
1771-
auto parameter = parameters[index];
1772-
auto argument = ((Type *)parameter)->subst(substitutions);
1772+
auto nominal = specialization->getAnyNominal();
1773+
auto requirements = GenericTypeRequirements(IGF.IGM, nominal);
1774+
int requirementIndex = 0;
1775+
for (auto requirement : requirements.getRequirements()) {
1776+
if (requirement.Protocol) {
1777+
continue;
1778+
}
1779+
auto parameter = requirement.TypeParameter;
1780+
auto argument = parameter.subst(substitutions);
17731781
llvm::Constant *addr =
17741782
IGM.getAddrOfTypeMetadata(argument->getCanonicalType());
17751783
auto addrInt = IGF.Builder.CreateBitCast(addr, IGM.Int8PtrTy);
17761784
condition = IGF.Builder.CreateAnd(
1777-
condition, IGF.Builder.CreateICmpEQ(addrInt, valueAtIndex(index)));
1785+
condition, IGF.Builder.CreateICmpEQ(addrInt, valueAtIndex(requirementIndex)));
1786+
++requirementIndex;
17781787
}
17791788
IGF.Builder.CreateCondBr(condition, specializationBlock, successorBlock);
17801789

@@ -1793,7 +1802,7 @@ static void emitCanonicalSpecializationsForGenericTypeMetadataAccessFunction(
17931802
response = IGF.Builder.CreateInsertValue(
17941803
response, state, 1, "insert metadata state into response");
17951804
specializationBlocks.push_back({specializationBlock, response});
1796-
++index;
1805+
++blockIndex;
17971806
}
17981807

17991808
for (auto pair : specializationBlocks) {

test/IRGen/conditional_conformances.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
// RUN: %target-swift-frontend -emit-ir %S/../Inputs/conditional_conformance_basic_conformances.swift | %FileCheck %S/../Inputs/conditional_conformance_basic_conformances.swift --check-prefix=CHECK --check-prefix=%target-os
2-
// RUN: %target-swift-frontend -emit-ir %S/../Inputs/conditional_conformance_with_assoc.swift | %FileCheck %S/../Inputs/conditional_conformance_with_assoc.swift --check-prefix=CHECK --check-prefix=%target-os
3-
// RUN: %target-swift-frontend -emit-ir %S/../Inputs/conditional_conformance_subclass.swift | %FileCheck %S/../Inputs/conditional_conformance_subclass.swift --check-prefix=CHECK --check-prefix=%target-os
4-
// RUN: %target-swift-frontend -emit-ir %S/../Inputs/conditional_conformance_recursive.swift | %FileCheck %S/../Inputs/conditional_conformance_recursive.swift --check-prefix=CHECK --check-prefix=%target-os
1+
// RUN: %target-swift-frontend -disable-generic-metadata-prespecialization -emit-ir %S/../Inputs/conditional_conformance_basic_conformances.swift | %FileCheck %S/../Inputs/conditional_conformance_basic_conformances.swift --check-prefix=CHECK --check-prefix=%target-os
2+
// RUN: %target-swift-frontend -disable-generic-metadata-prespecialization -emit-ir %S/../Inputs/conditional_conformance_with_assoc.swift | %FileCheck %S/../Inputs/conditional_conformance_with_assoc.swift --check-prefix=CHECK --check-prefix=%target-os
3+
// RUN: %target-swift-frontend -disable-generic-metadata-prespecialization -emit-ir %S/../Inputs/conditional_conformance_subclass.swift | %FileCheck %S/../Inputs/conditional_conformance_subclass.swift --check-prefix=CHECK --check-prefix=%target-os
4+
// RUN: %target-swift-frontend -disable-generic-metadata-prespecialization -emit-ir %S/../Inputs/conditional_conformance_recursive.swift | %FileCheck %S/../Inputs/conditional_conformance_recursive.swift --check-prefix=CHECK --check-prefix=%target-os
55

66
// Too many pointer-sized integers in the IR
77
// REQUIRES: PTRSIZE=64
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// RUN: %target-swift-frontend -target %module-target-future -emit-ir %S/../Inputs/conditional_conformance_basic_conformances.swift | %FileCheck %S/../Inputs/conditional_conformance_basic_conformances_future.swift -DINT=i%target-ptrsize --check-prefix=CHECK --check-prefix=%target-os
2+
// RUN: %target-swift-frontend -target %module-target-future -emit-ir %S/../Inputs/conditional_conformance_with_assoc.swift | %FileCheck %S/../Inputs/conditional_conformance_with_assoc_future.swift -DINT=i%target-ptrsize --check-prefix=CHECK --check-prefix=%target-os
3+
// RUN: %target-swift-frontend -target %module-target-future -emit-ir %S/../Inputs/conditional_conformance_subclass.swift | %FileCheck %S/../Inputs/conditional_conformance_subclass_future.swift -DINT=i%target-ptrsize --check-prefix=CHECK --check-prefix=%target-os
4+
// RUN: %target-swift-frontend -target %module-target-future -emit-ir %S/../Inputs/conditional_conformance_recursive.swift | %FileCheck %S/../Inputs/conditional_conformance_recursive.swift -DINT=i%target-ptrsize --check-prefix=CHECK --check-prefix=%target-os
5+
6+
// Too many pointer-sized integers in the IR
7+
// REQUIRES: PTRSIZE=64
8+
// REQUIRES: OS=macosx || OS=ios || OS=tvos || OS=watchos || OS=linux-gnu
9+

test/IRGen/conditional_conformances_gettypemetdatabyname.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
// RUN: %target-swift-frontend -target x86_64-apple-macosx10.99 -emit-ir %S/../Inputs/conditional_conformance_basic_conformances.swift | %FileCheck %S/../Inputs/conditional_conformance_basic_conformances.swift --check-prefix=TYPEBYNAME
1+
// RUN: %target-swift-frontend -disable-generic-metadata-prespecialization -target x86_64-apple-macosx10.99 -emit-ir %S/../Inputs/conditional_conformance_basic_conformances.swift | %FileCheck %S/../Inputs/conditional_conformance_basic_conformances.swift --check-prefix=TYPEBYNAME
2+
// RUN: %target-swift-frontend -target x86_64-apple-macosx10.99 -emit-ir %S/../Inputs/conditional_conformance_basic_conformances.swift | %FileCheck %S/../Inputs/conditional_conformance_basic_conformances.swift --check-prefix=TYPEBYNAME_PRESPECIALIZED
23

34
// Too many pointer-sized integers in the IR
45
// REQUIRES: PTRSIZE=64

test/IRGen/dynamic_self_metadata.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
// RUN: %target-swift-frontend %s -emit-ir -parse-as-library | %FileCheck %s
1+
// RUN: %target-swift-frontend -disable-generic-metadata-prespecialization %s -emit-ir -parse-as-library | %FileCheck %s
22

3+
// UNSUPPORTED: OS=windows-msvc
34
// REQUIRES: CPU=x86_64
45

56
// FIXME: Not a SIL test because we can't parse dynamic Self in SIL.
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
// RUN: %target-swift-frontend %s -target %module-target-future -emit-ir -parse-as-library | %FileCheck %s -DINT=i%target-ptrsize -DALIGNMENT=%target-alignment
2+
3+
4+
// REQUIRES: OS=macosx || OS=ios || OS=tvos || OS=watchos || OS=linux-gnu
5+
// REQUIRES: CPU=x86_64
6+
7+
// FIXME: Not a SIL test because we can't parse dynamic Self in SIL.
8+
// <rdar://problem/16931299>
9+
10+
// CHECK: [[TYPE:%.+]] = type <{ [8 x i8] }>
11+
12+
@inline(never) func id<T>(_ t: T) -> T {
13+
return t
14+
}
15+
// CHECK-LABEL: define hidden swiftcc void @"$s28dynamic_self_metadata_future2idyxxlF"
16+
17+
protocol P {
18+
associatedtype T
19+
}
20+
21+
extension P {
22+
func f() {}
23+
}
24+
25+
struct G<T> : P {
26+
var t: T
27+
}
28+
29+
class C {
30+
class func fromMetatype() -> Self? { return nil }
31+
// CHECK-LABEL: define hidden swiftcc i64 @"$s28dynamic_self_metadata_future1CC12fromMetatypeACXDSgyFZ"(%swift.type* swiftself)
32+
// CHECK: ret i64 0
33+
34+
func fromInstance() -> Self? { return nil }
35+
// CHECK-LABEL: define hidden swiftcc i64 @"$s28dynamic_self_metadata_future1CC12fromInstanceACXDSgyF"(%T28dynamic_self_metadata_future1CC* swiftself)
36+
// CHECK: ret i64 0
37+
38+
func dynamicSelfArgument() -> Self? {
39+
return id(nil)
40+
}
41+
// CHECK-LABEL: define hidden swiftcc i64 @"$s28dynamic_self_metadata_future1CC0A12SelfArgumentACXDSgyF"(%T28dynamic_self_metadata_future1CC* swiftself)
42+
// CHECK: [[GEP1:%.+]] = getelementptr {{.*}} %0
43+
// CHECK: [[TYPE1:%.+]] = load {{.*}} [[GEP1]]
44+
// CHECK: [[T0:%.+]] = call swiftcc %swift.metadata_response @"$sSqMa"(i64 0, %swift.type* [[TYPE1]])
45+
// CHECK: [[TYPE2:%.+]] = extractvalue %swift.metadata_response [[T0]], 0
46+
// CHECK: call swiftcc void @"$s28dynamic_self_metadata_future2idyxxlF"({{.*}}, %swift.type* [[TYPE2]])
47+
48+
func dynamicSelfConformingType() -> Self? {
49+
_ = G(t: self).f()
50+
return nil
51+
}
52+
// CHECK-LABEL: define hidden swiftcc i64 @"$s28dynamic_self_metadata_future1CC0A18SelfConformingTypeACXDSgyF"(%T28dynamic_self_metadata_future1CC* swiftself)
53+
// CHECK: [[SELF_GEP:%.+]] = getelementptr {{.*}} %0
54+
// CHECK: [[SELF_TYPE:%.+]] = load {{.*}} [[SELF_GEP]]
55+
// CHECK: call i8** @swift_getWitnessTable(
56+
// CHECK-SAME: %swift.protocol_conformance_descriptor* bitcast (
57+
// CHECK-SAME: {{.*}} @"$s28dynamic_self_metadata_future1GVyxGAA1PAAMc"
58+
// CHECK-SAME: to %swift.protocol_conformance_descriptor*
59+
// CHECK-SAME: ),
60+
// CHECK-SAME: %swift.type* getelementptr inbounds (
61+
// CHECK-SAME: %swift.full_type,
62+
// CHECK-SAME: %swift.full_type* bitcast (
63+
// CHECK-SAME: <{
64+
// CHECK-SAME: i8**,
65+
// CHECK-SAME: [[INT]],
66+
// CHECK-SAME: %swift.type_descriptor*,
67+
// CHECK-SAME: %swift.type*,
68+
// CHECK-SAME: i32,
69+
// CHECK-SAME: {{(\[4 x i8\])?}},
70+
// CHECK-SAME: i64
71+
// CHECK-SAME: }>* @"$s28dynamic_self_metadata_future1GVyAA1CCXDGMf"
72+
// CHECK-SAME: to %swift.full_type*
73+
// CHECK-SAME: ),
74+
// CHECK-SAME: i32 0,
75+
// CHECK-SAME: i32 1
76+
// CHECK-SAME: ),
77+
// CHECK-SAME: i8*** undef
78+
// CHECK-SAME: )
79+
}

test/IRGen/foreign_types.sil

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-swift-frontend -I %S/Inputs/abi %s -emit-ir | %FileCheck %s -DINT=i%target-ptrsize
1+
// RUN: %target-swift-frontend -disable-generic-metadata-prespecialization -I %S/Inputs/abi %s -emit-ir | %FileCheck %s -DINT=i%target-ptrsize
22

33
sil_stage canonical
44
import c_layout

test/IRGen/foreign_types_future.sil

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// RUN: %target-swift-frontend -target %module-target-future -I %S/Inputs/abi %s -emit-ir | %FileCheck %s -DINT=i%target-ptrsize
2+
3+
// REQUIRES: OS=macosx || OS=ios || OS=tvos || OS=watchos || OS=linux-gnu
4+
// UNSUPPORTED: CPU=i386 && OS=ios
5+
// UNSUPPORTED: CPU=armv7 && OS=ios
6+
// UNSUPPORTED: CPU=armv7s && OS=ios
7+
8+
sil_stage canonical
9+
import c_layout
10+
11+
// CHECK: [[AMAZING_COLOR_NAME:@.*]] = private constant [13 x i8] c"AmazingColor\00"
12+
13+
// CHECK-LABEL: @"$sSo12AmazingColorVMn" = linkonce_odr hidden constant
14+
// CHECK-SAME: [[AMAZING_COLOR_NAME]]
15+
// CHECK-SAME: @"$sSo12AmazingColorVMa"
16+
17+
// CHECK: [[HAS_NESTED_UNION_NAME:@.*]] = private constant [15 x i8] c"HasNestedUnion\00"
18+
19+
// CHECK-LABEL: @"$sSo14HasNestedUnionVMn" = linkonce_odr hidden constant
20+
// CHECK-SAME: [[HAS_NESTED_UNION_NAME]]
21+
// CHECK-SAME: @"$sSo14HasNestedUnionVMa"
22+
23+
// CHECK-LABEL: @"$sSo14HasNestedUnionV18__Unnamed_struct_sVMf" = linkonce_odr hidden constant
24+
// CHECK-SAME: @"$sSo14HasNestedUnionV18__Unnamed_struct_sVWV"
25+
// CHECK-SAME: [[INT]] 512,
26+
// CHECK-SAME: @"$sSo14HasNestedUnionV18__Unnamed_struct_sVMn"
27+
// CHECK-SAME: i32 0,
28+
// CHECK-SAME: i32 4,
29+
// CHECK-SAME: i64 0 }
30+
31+
// CHECK-LABEL: @"\01l_type_metadata_table" = private constant
32+
// CHECK-SAME: @"$sSo12AmazingColorVMn"
33+
// CHECK-SAME: @"$sSo14HasNestedUnionVMn"
34+
// CHECK-SAME: @"$sSo14HasNestedUnionV18__Unnamed_struct_sVMn"
35+
36+
sil @test0 : $() -> () {
37+
bb0:
38+
%0 = metatype $@thick HasNestedUnion.Type
39+
%1 = metatype $@thick AmazingColor.Type
40+
41+
%ret = tuple ()
42+
return %ret : $()
43+
}
44+

0 commit comments

Comments
 (0)