Skip to content

Commit 8866a2d

Browse files
Merge pull request swiftlang#39656 from aschwaighofer/delay_import_prespecializations
Delay import of prespecialized decls until generic specialization
2 parents ab2a799 + 5fd4883 commit 8866a2d

File tree

10 files changed

+112
-66
lines changed

10 files changed

+112
-66
lines changed

include/swift/SIL/SILModule.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ class SILUndef;
109109
class SourceFile;
110110
class SerializedSILLoader;
111111
class SILFunctionBuilder;
112+
class SILOptFunctionBuilder;
112113
class SILRemarkStreamer;
113114

114115
namespace Lowering {
@@ -353,6 +354,8 @@ class SILModule {
353354
/// This gets set in OwnershipModelEliminator pass.
354355
bool regDeserializationNotificationHandlerForAllFuncOME;
355356

357+
bool prespecializedFunctionDeclsImported;
358+
356359
/// Action to be executed for serializing the SILModule.
357360
ActionCallback SerializeSILAction;
358361

@@ -894,6 +897,10 @@ class SILModule {
894897
/// declaration context ought to be serialized as part of this module.
895898
bool
896899
shouldSerializeEntitiesAssociatedWithDeclContext(const DeclContext *DC) const;
900+
901+
/// Gather prespecialized from extensions.
902+
void performOnceForPrespecializedImportedExtensions(
903+
llvm::function_ref<void(AbstractFunctionDecl *)> action);
897904
};
898905

899906
inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const SILModule &M){

lib/SIL/IR/SILFunctionBuilder.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -184,10 +184,13 @@ SILFunction *SILFunctionBuilder::getOrCreateFunction(
184184
// assert.
185185
assert(mod.getStage() == SILStage::Raw ||
186186
fn->getLoweredFunctionType() == constantType);
187+
auto linkageForDef = constant.getLinkage(ForDefinition_t::ForDefinition);
188+
auto fnLinkage = fn->getLinkage();
187189
assert(mod.getStage() == SILStage::Raw || fn->getLinkage() == linkage ||
188190
(forDefinition == ForDefinition_t::NotForDefinition &&
189-
fn->getLinkage() ==
190-
constant.getLinkage(ForDefinition_t::ForDefinition)));
191+
(fnLinkage == linkageForDef ||
192+
(linkageForDef == SILLinkage::PublicNonABI &&
193+
fnLinkage == SILLinkage::SharedExternal))));
191194
if (forDefinition) {
192195
// In all the cases where getConstantLinkage returns something
193196
// different for ForDefinition, it returns an available-externally

lib/SIL/IR/SILModule.cpp

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,8 @@ SILModule::SILModule(llvm::PointerUnion<FileUnit *, ModuleDecl *> context,
9898
Options(Options), serialized(false),
9999
regDeserializationNotificationHandlerForNonTransparentFuncOME(false),
100100
regDeserializationNotificationHandlerForAllFuncOME(false),
101-
SerializeSILAction(), Types(TC) {
101+
prespecializedFunctionDeclsImported(false), SerializeSILAction(),
102+
Types(TC) {
102103
assert(!context.isNull());
103104
if (auto *file = context.dyn_cast<FileUnit *>()) {
104105
AssociatedDeclContext = file;
@@ -874,6 +875,42 @@ void SILModule::installSILRemarkStreamer() {
874875
bool SILModule::isStdlibModule() const {
875876
return TheSwiftModule->isStdlibModule();
876877
}
878+
void SILModule::performOnceForPrespecializedImportedExtensions(
879+
llvm::function_ref<void(AbstractFunctionDecl *)> action) {
880+
if (prespecializedFunctionDeclsImported)
881+
return;
882+
883+
SmallVector<ModuleDecl *, 8> importedModules;
884+
// Add the Swift module.
885+
if (!isStdlibModule()) {
886+
auto *SwiftStdlib = getASTContext().getStdlibModule(true);
887+
if (SwiftStdlib)
888+
importedModules.push_back(SwiftStdlib);
889+
}
890+
891+
// Add explicitly imported modules.
892+
SmallVector<Decl *, 32> topLevelDecls;
893+
getSwiftModule()->getTopLevelDecls(topLevelDecls);
894+
for (const Decl *D : topLevelDecls) {
895+
if (auto importDecl = dyn_cast<ImportDecl>(D)) {
896+
if (!importDecl->getModule() ||
897+
importDecl->getModule()->isNonSwiftModule())
898+
continue;
899+
importedModules.push_back(importDecl->getModule());
900+
}
901+
}
902+
903+
for (auto *module : importedModules) {
904+
SmallVector<Decl *, 16> prespecializations;
905+
module->getExportedPrespecializations(prespecializations);
906+
for (auto *p : prespecializations) {
907+
if (auto *vd = dyn_cast<AbstractFunctionDecl>(p)) {
908+
action(vd);
909+
}
910+
}
911+
}
912+
prespecializedFunctionDeclsImported = true;
913+
}
877914

878915
SILProperty *SILProperty::create(SILModule &M,
879916
bool Serialized,

lib/SILGen/SILGen.cpp

Lines changed: 0 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -2203,52 +2203,3 @@ swift::performASTLowering(FileUnit &sf, Lowering::TypeConverter &tc,
22032203
auto desc = ASTLoweringDescriptor::forFile(sf, tc, options);
22042204
return llvm::cantFail(sf.getASTContext().evaluator(ASTLoweringRequest{desc}));
22052205
}
2206-
2207-
static void transferSpecializeAttributeTargets(SILGenModule &SGM, SILModule &M,
2208-
Decl *d) {
2209-
auto *vd = cast<AbstractFunctionDecl>(d);
2210-
for (auto *A : vd->getAttrs().getAttributes<SpecializeAttr>()) {
2211-
auto *SA = cast<SpecializeAttr>(A);
2212-
// Filter _spi.
2213-
auto spiGroups = SA->getSPIGroups();
2214-
auto hasSPIGroup = !spiGroups.empty();
2215-
if (hasSPIGroup) {
2216-
if (vd->getModuleContext() != M.getSwiftModule() &&
2217-
!M.getSwiftModule()->isImportedAsSPI(SA, vd)) {
2218-
continue;
2219-
}
2220-
}
2221-
if (auto *targetFunctionDecl = SA->getTargetFunctionDecl(vd)) {
2222-
auto target = SILDeclRef(targetFunctionDecl);
2223-
auto targetSILFunction = SGM.getFunction(target, NotForDefinition);
2224-
auto kind = SA->getSpecializationKind() ==
2225-
SpecializeAttr::SpecializationKind::Full
2226-
? SILSpecializeAttr::SpecializationKind::Full
2227-
: SILSpecializeAttr::SpecializationKind::Partial;
2228-
Identifier spiGroupIdent;
2229-
if (hasSPIGroup) {
2230-
spiGroupIdent = spiGroups[0];
2231-
}
2232-
auto availability =
2233-
AvailabilityInference::annotatedAvailableRangeForAttr(SA,
2234-
M.getSwiftModule()->getASTContext());
2235-
targetSILFunction->addSpecializeAttr(SILSpecializeAttr::create(
2236-
M, SA->getSpecializedSignature(), SA->isExported(), kind, nullptr,
2237-
spiGroupIdent, vd->getModuleContext(), availability));
2238-
}
2239-
}
2240-
}
2241-
2242-
void SILGenModule::visitImportDecl(ImportDecl *import) {
2243-
auto *module = import->getModule();
2244-
if (module->isNonSwiftModule())
2245-
return;
2246-
2247-
SmallVector<Decl*, 16> prespecializations;
2248-
module->getExportedPrespecializations(prespecializations);
2249-
for (auto *p : prespecializations) {
2250-
if (auto *vd = dyn_cast<AbstractFunctionDecl>(p)) {
2251-
transferSpecializeAttributeTargets(*this, M, vd);
2252-
}
2253-
}
2254-
}

lib/SILGen/SILGen.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,7 @@ class LLVM_LIBRARY_VISIBILITY SILGenModule : public ASTVisitor<SILGenModule> {
265265

266266
// These are either not allowed at global scope or don't require
267267
// code emission.
268-
void visitImportDecl(ImportDecl *d);
268+
void visitImportDecl(ImportDecl *d) {}
269269
void visitEnumCaseDecl(EnumCaseDecl *d) {}
270270
void visitEnumElementDecl(EnumElementDecl *d) {}
271271
void visitOperatorDecl(OperatorDecl *d) {}

lib/SILOptimizer/Utils/Generics.cpp

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#define DEBUG_TYPE "generic-specializer"
1414

1515
#include "swift/SILOptimizer/Utils/Generics.h"
16+
#include "swift/AST/Decl.h"
1617
#include "swift/AST/DiagnosticEngine.h"
1718
#include "swift/AST/DiagnosticsSIL.h"
1819
#include "swift/AST/GenericEnvironment.h"
@@ -2520,6 +2521,45 @@ usePrespecialized(SILOptFunctionBuilder &funcBuilder, ApplySite apply,
25202521
return nullptr;
25212522
}
25222523

2524+
static void transferSpecializeAttributeTargets(SILModule &M,
2525+
SILOptFunctionBuilder &builder,
2526+
Decl *d) {
2527+
auto *vd = cast<AbstractFunctionDecl>(d);
2528+
for (auto *A : vd->getAttrs().getAttributes<SpecializeAttr>()) {
2529+
auto *SA = cast<SpecializeAttr>(A);
2530+
// Filter _spi.
2531+
auto spiGroups = SA->getSPIGroups();
2532+
auto hasSPIGroup = !spiGroups.empty();
2533+
if (hasSPIGroup) {
2534+
if (vd->getModuleContext() != M.getSwiftModule() &&
2535+
!M.getSwiftModule()->isImportedAsSPI(SA, vd)) {
2536+
continue;
2537+
}
2538+
}
2539+
if (auto *targetFunctionDecl = SA->getTargetFunctionDecl(vd)) {
2540+
auto target = SILDeclRef(targetFunctionDecl);
2541+
auto targetSILFunction = builder.getOrCreateFunction(
2542+
SILLocation(vd), target, NotForDefinition,
2543+
[&builder](SILLocation loc, SILDeclRef constant) -> SILFunction * {
2544+
return builder.getOrCreateFunction(loc, constant, NotForDefinition);
2545+
});
2546+
auto kind = SA->getSpecializationKind() ==
2547+
SpecializeAttr::SpecializationKind::Full
2548+
? SILSpecializeAttr::SpecializationKind::Full
2549+
: SILSpecializeAttr::SpecializationKind::Partial;
2550+
Identifier spiGroupIdent;
2551+
if (hasSPIGroup) {
2552+
spiGroupIdent = spiGroups[0];
2553+
}
2554+
auto availability = AvailabilityInference::annotatedAvailableRangeForAttr(
2555+
SA, M.getSwiftModule()->getASTContext());
2556+
targetSILFunction->addSpecializeAttr(SILSpecializeAttr::create(
2557+
M, SA->getSpecializedSignature(), SA->isExported(), kind, nullptr,
2558+
spiGroupIdent, vd->getModuleContext(), availability));
2559+
}
2560+
}
2561+
}
2562+
25232563
void swift::trySpecializeApplyOfGeneric(
25242564
SILOptFunctionBuilder &FuncBuilder,
25252565
ApplySite Apply, DeadInstructionSet &DeadApplies,
@@ -2573,6 +2613,13 @@ void swift::trySpecializeApplyOfGeneric(
25732613
// Check if there is a pre-specialization available in a library.
25742614
SILFunction *prespecializedF = nullptr;
25752615
ReabstractionInfo prespecializedReInfo;
2616+
2617+
FuncBuilder.getModule().performOnceForPrespecializedImportedExtensions(
2618+
[&FuncBuilder](AbstractFunctionDecl *pre) {
2619+
transferSpecializeAttributeTargets(FuncBuilder.getModule(), FuncBuilder,
2620+
pre);
2621+
});
2622+
25762623
if ((prespecializedF = usePrespecialized(FuncBuilder, Apply, RefF, ReInfo,
25772624
prespecializedReInfo))) {
25782625
ReInfo = prespecializedReInfo;

test/IRGen/dllimport.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
// RUN: %swift -target thumbv7--windows-itanium -emit-ir -parse-as-library -disable-legacy-type-info -parse-stdlib -module-name dllimport %s -o - -enable-source-import -I %S | %FileCheck %s -check-prefix CHECK -check-prefix CHECK-NO-OPT
2-
// RUN: %swift -target thumbv7--windows-itanium -O -emit-ir -parse-as-library -disable-legacy-type-info -parse-stdlib -module-name dllimport -primary-file %s -o - -enable-source-import -I %S | %FileCheck %s -check-prefix CHECK -check-prefix CHECK-OPT
1+
// RUN: %swift -Xllvm -sil-disable-pass=GenericSpecializer -target thumbv7--windows-itanium -emit-ir -parse-as-library -disable-legacy-type-info -parse-stdlib -module-name dllimport %s -o - -enable-source-import -I %S | %FileCheck %s -check-prefix CHECK -check-prefix CHECK-NO-OPT
2+
// RUN: %swift -Xllvm -sil-disable-pass=GenericSpecializer -target thumbv7--windows-itanium -O -emit-ir -parse-as-library -disable-legacy-type-info -parse-stdlib -module-name dllimport -primary-file %s -o - -enable-source-import -I %S | %FileCheck %s -check-prefix CHECK -check-prefix CHECK-OPT
33

44
// REQUIRES: CODEGENERATOR=ARM
55

test/SILGen/specialize_attr.swift

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// RUN: %target-swift-frontend -module-name A -emit-module-path %t/A.swiftmodule -enable-library-evolution -swift-version 5 %S/Inputs/specialize_attr_module.swift
44
// RUN: %target-swift-frontend -I %t -module-name B -emit-module-path %t/B.swiftmodule -enable-library-evolution -swift-version 5 %S/Inputs/specialize_attr_module2.swift
55
// RUN: %target-swift-emit-silgen -I %t -module-name specialize_attr -emit-verbose-sil %s -swift-version 5 | %FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-%target-os
6-
// RUN: %target-swift-emit-sil -I %t -sil-verify-all -O -module-name specialize_attr -emit-verbose-sil %s | %FileCheck -check-prefix=CHECK-OPT -check-prefix=CHECK-OPT-EVO %s
6+
// RUN: %target-swift-emit-sil -I %t -sil-verify-all -O -module-name specialize_attr -emit-verbose-sil %s | %FileCheck -check-prefix=CHECK-OPT -check-prefix=CHECK-OPT-EVO -check-prefix=CHECK-OPT-%target-os %s
77

88
// Test .swiftinterface
99
// RUN: %empty-directory(%t)
@@ -124,15 +124,15 @@ public struct CC2<T : PP> {
124124
}
125125

126126
// Import from module A and B.
127-
// CHECK-macosx-LABEL: sil [serialized] [_specialize exported: true, kind: full, where T == Double] [_specialize exported: true, kind: full, available: 10.50, where T == Int16] [_specialize exported: true, kind: full, where T == Int] @$s1A11PublicThingV11doStuffWithyyxF : $@convention(method) <τ_0_0> (@in_guaranteed τ_0_0, PublicThing<τ_0_0>) -> ()
128-
// CHECK-linux-gnu-LABEL: sil [serialized] [_specialize exported: true, kind: full, where T == Double] [_specialize exported: true, kind: full, where T == Int16] [_specialize exported: true, kind: full, where T == Int] @$s1A11PublicThingV11doStuffWithyyxF : $@convention(method) <τ_0_0> (@in_guaranteed τ_0_0, PublicThing<τ_0_0>) -> ()
129-
// CHECK-LABEL: sil [serialized] [_specialize exported: true, kind: full, where T == Double] [_specialize exported: true, kind: full, where T == Int] @$s1A13InternalThingV11doStuffWith5boxedyAA05BoxedB0VyxG_tF : $@convention(method) <τ_0_0> (BoxedThing<τ_0_0>, InternalThing<τ_0_0>) -> ()
127+
// CHECK-OPT-macosx-DAG: sil {{.*}} [_specialize exported: true, kind: full, where T == Double] [_specialize exported: true, kind: full, available: 10.50, where T == Int16] [_specialize exported: true, kind: full, where T == Int] @$s1A11PublicThingV11doStuffWithyyxF : $@convention(method) <T> (@in_guaranteed T, PublicThing<T>) -> ()
128+
// CHECK-OPT-linux-gnu-DAG: sil {{.*}} [_specialize exported: true, kind: full, where T == Double] [_specialize exported: true, kind: full, where T == Int16] [_specialize exported: true, kind: full, where T == Int] @$s1A11PublicThingV11doStuffWithyyxF : $@convention(method) <T> (@in_guaranteed T, PublicThing<T>) -> ()
129+
// CHECK-OPT-DAG: sil {{.*}} [_specialize exported: true, kind: full, where T == Double] [_specialize exported: true, kind: full, where T == Int] @$s1A13InternalThingV11doStuffWith5boxedyAA05BoxedB0VyxG_tF : $@convention(method) <T> (BoxedThing<T>, InternalThing<T>) -> ()
130130

131-
// CHECK-DAG: sil [serialized] [_specialize exported: true, kind: full, where T == Int] @$s1A14InternalThing2V9computedZxvM : $@yield_once @convention(method) <τ_0_0> (@inout InternalThing2<τ_0_0>) -> @yields @inout τ_0_0
132-
// CHECK-DAG: sil [serialized] [_specialize exported: true, kind: full, where T == Int] @$s1A14InternalThing2V9computedZxvr : $@yield_once @convention(method) <τ_0_0> (@in_guaranteed InternalThing2<τ_0_0>) -> @yields @in_guaranteed τ_0_0
131+
// CHECK-OPT-DAG: sil {{.*}} [_specialize exported: true, kind: full, where T == Int] @$s1A14InternalThing2V9computedZxvM : $@yield_once @convention(method) <T> (@inout InternalThing2<T>) -> @yields @inout T
132+
// CHECK-OPT-DAG: sil {{.*}} [_specialize exported: true, kind: full, where T == Int] @$s1A14InternalThing2V9computedZxvr : $@yield_once @convention(method) <T> (@in_guaranteed InternalThing2<T>) -> @yields @in_guaranteed T
133133

134-
// CHECK-DAG: sil [serialized] [_specialize exported: true, kind: full, where T == Int] @$s1A14InternalThing2VyxSicig : $@convention(method) <τ_0_0> (Int, @in_guaranteed InternalThing2<τ_0_0>) -> @out τ_0_0
135-
// CHECK-DAG: sil [serialized] [_specialize exported: true, kind: full, where T == Int] @$s1A14InternalThing2VyxSicis : $@convention(method) <τ_0_0> (@in τ_0_0, Int, @inout InternalThing2<τ_0_0>) -> ()
134+
// CHECK-OPT-DAG: sil {{.*}} [_specialize exported: true, kind: full, where T == Int] @$s1A14InternalThing2VyxSicig : $@convention(method) <T> (Int, @in_guaranteed InternalThing2<T>) -> @out T
135+
// CHECK-OPT-DAG: sil {{.*}} [_specialize exported: true, kind: full, where T == Int] @$s1A14InternalThing2VyxSicis : $@convention(method) <T> (@in T, Int, @inout InternalThing2<T>) -> ()
136136

137137
// CHECK-LABEL: sil [_specialize exported: false, kind: full, where T == Klass1, U == FakeString] [_specialize exported: false, kind: full, where T == Int, U == Float] [ossa] @$s15specialize_attr0A4This_1uyx_q_tr0_lF : $@convention(thin) <T, U> (@in_guaranteed T, @in_guaranteed U) -> () {
138138

test/SILOptimizer/pre_specialize-macos.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,6 @@
99
import pre_specialized_module
1010
import pre_specialized_module2
1111

12-
// OPT: sil [available 10.50] [noinline] @$s22pre_specialized_module21publicPrespecialized2yyxlFAA8SomeDataV_Ts5 : $@convention(thin) (SomeData) -> ()
13-
// OPT: sil [available 10.50] [noinline] @$s22pre_specialized_module21publicPrespecialized2yyxlF0a1_B8_module213SomeOtherDataV_Ts5 : $@convention(thin) (SomeOtherData) -> ()
14-
1512
// CHECK: sil @$s4main28usePrespecializedEntryPointsyyF : $@convention(thin) () -> () {
1613
// OPT: [[F1:%.*]] = function_ref @$s22pre_specialized_module21publicPrespecialized2yyxlFAA8SomeDataV_Ts5 : $@convention(thin) (SomeData) -> ()
1714
// OPT: apply [[F1]](
@@ -28,3 +25,6 @@ public func usePrespecializedEntryPoints() {
2825
publicPrespecialized2(SomeData())
2926
publicPrespecialized2(SomeOtherData())
3027
}
28+
29+
// OPT: sil [available 10.50] [noinline] @$s22pre_specialized_module21publicPrespecialized2yyxlFAA8SomeDataV_Ts5 : $@convention(thin) (SomeData) -> ()
30+
// OPT: sil [available 10.50] [noinline] @$s22pre_specialized_module21publicPrespecialized2yyxlF0a1_B8_module213SomeOtherDataV_Ts5 : $@convention(thin) (SomeOtherData) -> ()

test/SILOptimizer/specialize_checked_cast_branch.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,4 +338,5 @@ _ = ExistentialToArchetypeCast(o: o, t: b)
338338
// CHECK-NOT: checked_cast_br %
339339
// CHECK: return %0 : $AnyObject
340340
// CHECK-NOT: checked_cast_br %
341+
// CHECK: } // end sil function '$s30specialize_checked_cast_branch26ExistentialToArchetypeCast1o1txyXl_xtlFyXl_Tg5'
341342
_ = ExistentialToArchetypeCast(o: o, t: o)

0 commit comments

Comments
 (0)