Skip to content

Commit 27bcabc

Browse files
committed
Improve handling of pre-specializations.
This commit does not result in any visible functionality changes yet. This is a preparation for some changes on the swift-3-indexing branch.
1 parent 9234eb3 commit 27bcabc

File tree

3 files changed

+84
-37
lines changed

3 files changed

+84
-37
lines changed

lib/SILOptimizer/IPO/UsePrespecialized.cpp

+19-4
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,9 @@ bool UsePrespecialized::replaceByPrespecialized(SILFunction &F) {
7575
if (!ReferencedF)
7676
continue;
7777

78+
DEBUG(llvm::dbgs() << "Trying to use specialized function for:\n";
79+
AI.getInstruction()->dumpInContext());
80+
7881
// Check if it is a call of a generic function.
7982
// If this is the case, check if there is a specialization
8083
// available for it already and use this specialization
@@ -114,12 +117,22 @@ bool UsePrespecialized::replaceByPrespecialized(SILFunction &F) {
114117
// If we already have this specialization, reuse it.
115118
auto PrevF = M.lookUpFunction(ClonedName);
116119
if (PrevF) {
120+
DEBUG(llvm::dbgs() << "Found a specialization: " << ClonedName << "\n");
117121
if (PrevF->getLinkage() != SILLinkage::SharedExternal)
118122
NewF = PrevF;
119-
} else {
123+
else {
124+
DEBUG(llvm::dbgs() << "Wrong linkage: " << (int)PrevF->getLinkage()
125+
<< "\n");
126+
}
127+
}
128+
129+
if (!PrevF || !NewF) {
120130
// Check for the existence of this function in another module without
121131
// loading the function body.
122132
PrevF = lookupPrespecializedSymbol(M, ClonedName);
133+
DEBUG(llvm::dbgs()
134+
<< "Checked if there is a specialization in a different module: "
135+
<< PrevF << "\n");
123136
if (!PrevF)
124137
continue;
125138
NewF = PrevF;
@@ -128,10 +141,12 @@ bool UsePrespecialized::replaceByPrespecialized(SILFunction &F) {
128141
if (!NewF)
129142
continue;
130143

144+
assert(NewF->isExternalDeclaration() &&
145+
"Prespecialized function should be an external declaration");
146+
131147
// An existing specialization was found.
132-
DEBUG(
133-
llvm::dbgs() << "Found a specialization of " << ReferencedF->getName()
134-
<< " : " << NewF->getName() << "\n");
148+
DEBUG(llvm::dbgs() << "Found a specialization of " << ReferencedF->getName()
149+
<< " : " << NewF->getName() << "\n");
135150

136151
auto NewAI = replaceWithSpecializedFunction(AI, NewF, ReInfo);
137152
AI.getInstruction()->replaceAllUsesWith(NewAI.getInstruction());

lib/SILOptimizer/Utils/Generics.cpp

+61-33
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ ReabstractionInfo::ReabstractionInfo(SILFunction *OrigF,
4141
if (hasUnboundGenericTypes(InterfaceSubs)) {
4242
DEBUG(llvm::dbgs() <<
4343
" Cannot specialize with unbound interface substitutions.\n");
44+
DEBUG(for (auto Sub : ParamSubs) {
45+
Sub.dump();
46+
});
4447
return;
4548
}
4649
if (hasDynamicSelfTypes(InterfaceSubs)) {
@@ -167,8 +170,12 @@ SILFunction *GenericFuncSpecializer::lookupSpecialization() {
167170
assert(ReInfo.getSpecializedType()
168171
== SpecializedF->getLoweredFunctionType() &&
169172
"Previously specialized function does not match expected type.");
173+
DEBUG(llvm::dbgs() << "Found an existing specialization for: " << ClonedName
174+
<< "\n");
170175
return SpecializedF;
171176
}
177+
DEBUG(llvm::dbgs() << "Could not find an existing specialization for: "
178+
<< ClonedName << "\n");
172179
return nullptr;
173180
}
174181

@@ -400,7 +407,8 @@ void swift::trySpecializeApplyOfGeneric(
400407
auto *F = Apply.getInstruction()->getFunction();
401408
auto *RefF = cast<FunctionRefInst>(Apply.getCallee())->getReferencedFunction();
402409

403-
DEBUG(llvm::dbgs() << " ApplyInst: " << *Apply.getInstruction());
410+
DEBUG(llvm::dbgs() << " ApplyInst:\n";
411+
Apply.getInstruction()->dumpInContext());
404412

405413
// If the caller is fragile but the callee is not, bail out.
406414
// Specializations have shared linkage, which means they do
@@ -470,6 +478,9 @@ void swift::trySpecializeApplyOfGeneric(
470478
== SpecializedF->isFragile() &&
471479
"Previously specialized function does not match expected "
472480
"resilience level.");
481+
// Even if the pre-specialization exists already, try to preserve it
482+
// if it is whitelisted.
483+
linkSpecialization(M, SpecializedF);
473484
} else {
474485
SpecializedF = FuncSpecializer.tryCreateSpecialization();
475486
if (!SpecializedF)
@@ -534,8 +545,29 @@ void swift::trySpecializeApplyOfGeneric(
534545
// This uses the SIL linker to checks for the does not load the body of the pres
535546
// =============================================================================
536547

548+
static void keepSpecializationAsPublic(SILFunction *F) {
549+
DEBUG(auto DemangledNameString =
550+
swift::Demangle::demangleSymbolAsString(F->getName());
551+
StringRef DemangledName = DemangledNameString;
552+
llvm::dbgs() << "Keep specialization public: " << DemangledName << " : "
553+
<< F->getName() << "\n");
554+
// Make it public, so that others can refer to it.
555+
//
556+
// NOTE: This function may refer to non-public symbols, which may lead to
557+
// problems, if you ever try to inline this function. Therefore, these
558+
// specializations should only be used to refer to them, but should never
559+
// be inlined! The general rule could be: Never inline specializations
560+
// from stdlib!
561+
//
562+
// NOTE: Making these specializations public at this point breaks
563+
// some optimizations. Therefore, just mark the function.
564+
// DeadFunctionElimination pass will check if the function is marked
565+
// and preserve it if required.
566+
F->setKeepAsPublic(true);
567+
}
568+
537569
/// Link a specialization for generating prespecialized code.
538-
///
570+
///
539571
/// For now, it is performed only for specializations in the
540572
/// standard library. But in the future, one could think of
541573
/// maintaining a cache of optimized specializations.
@@ -545,34 +577,14 @@ void swift::trySpecializeApplyOfGeneric(
545577
/// the library, but only used only by client code compiled at -Onone. They
546578
/// should be never inlined.
547579
static bool linkSpecialization(SILModule &M, SILFunction *F) {
580+
if (F->isKeepAsPublic())
581+
return true;
548582
// Do not remove functions from the white-list. Keep them around.
549583
// Change their linkage to public, so that other applications can refer to it.
550-
551584
if (M.getOptions().Optimization >= SILOptions::SILOptMode::Optimize &&
552-
F->getLinkage() != SILLinkage::Public &&
553585
F->getModule().getSwiftModule()->getName().str() == SWIFT_ONONE_SUPPORT) {
554-
if (F->getLinkage() != SILLinkage::Public &&
555-
isWhitelistedSpecialization(F->getName())) {
556-
557-
DEBUG(
558-
auto DemangledNameString =
559-
swift::Demangle::demangleSymbolAsString(F->getName());
560-
StringRef DemangledName = DemangledNameString;
561-
llvm::dbgs() << "Keep specialization: " << DemangledName << " : "
562-
<< F->getName() << "\n");
563-
// Make it public, so that others can refer to it.
564-
//
565-
// NOTE: This function may refer to non-public symbols, which may lead to
566-
// problems, if you ever try to inline this function. Therefore, these
567-
// specializations should only be used to refer to them, but should never
568-
// be inlined! The general rule could be: Never inline specializations
569-
// from stdlib!
570-
//
571-
// NOTE: Making these specializations public at this point breaks
572-
// some optimizations. Therefore, just mark the function.
573-
// DeadFunctionElimination pass will check if the function is marked
574-
// and preserve it if required.
575-
F->setKeepAsPublic(true);
586+
if (isWhitelistedSpecialization(F->getName())) {
587+
keepSpecializationAsPublic(F);
576588
return true;
577589
}
578590
}
@@ -607,7 +619,10 @@ bool swift::isWhitelistedSpecialization(StringRef SpecName) {
607619

608620
StringRef DemangledName = DemangledNameString;
609621

622+
DEBUG(llvm::dbgs() << "Check if whitelisted: " << DemangledName << "\n");
623+
610624
auto pos = DemangledName.find("generic ", 0);
625+
auto oldpos = pos;
611626
if (pos == StringRef::npos)
612627
return false;
613628

@@ -618,11 +633,22 @@ bool swift::isWhitelistedSpecialization(StringRef SpecName) {
618633
buffer << STDLIB_NAME <<'.';
619634

620635
StringRef OfStr = buffer.str();
621-
622-
pos = DemangledName.find(OfStr, pos);
623-
624-
if (pos == StringRef::npos)
625-
return false;
636+
DEBUG(llvm::dbgs() << "Check substring: " << OfStr << "\n");
637+
638+
pos = DemangledName.find(OfStr, oldpos);
639+
640+
if (pos == StringRef::npos) {
641+
// Create "of (extension in Swift).Swift"
642+
llvm::SmallString<64> OfString;
643+
llvm::raw_svector_ostream buffer(OfString);
644+
buffer << "of (extension in " << STDLIB_NAME << "):";
645+
buffer << STDLIB_NAME << '.';
646+
OfStr = buffer.str();
647+
pos = DemangledName.find(OfStr, oldpos);
648+
DEBUG(llvm::dbgs() << "Check substring: " << OfStr << "\n");
649+
if (pos == StringRef::npos)
650+
return false;
651+
}
626652

627653
pos += OfStr.size();
628654

@@ -659,8 +685,10 @@ SILFunction *swift::lookupPrespecializedSymbol(SILModule &M,
659685
StringRef FunctionName) {
660686
// First check if the module contains a required specialization already.
661687
auto *Specialization = M.lookUpFunction(FunctionName);
662-
if (Specialization)
663-
return Specialization;
688+
if (Specialization) {
689+
if (Specialization->getLinkage() == SILLinkage::PublicExternal)
690+
return Specialization;
691+
}
664692

665693
// Then check if the required specialization can be found elsewhere.
666694
Specialization = lookupExistingSpecialization(M, FunctionName);

stdlib/public/SwiftOnoneSupport/SwiftOnoneSupport.swift

+4
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,10 @@ struct _Prespecialize {
152152
for i in 0..<a.count {
153153
count += a[i]
154154
}
155+
// Specialize Range for integers
156+
for j in 0...a.count - 1{
157+
count += a[j]
158+
}
155159
return count
156160
}
157161
}

0 commit comments

Comments
 (0)