Skip to content

Commit 997fc5d

Browse files
Merge pull request #33140 from aschwaighofer/eager_specializer_function_pass
Convert the EagerSpecializer pass to a function pass
2 parents 2308bb1 + ecf9fbd commit 997fc5d

File tree

4 files changed

+69
-55
lines changed

4 files changed

+69
-55
lines changed

lib/SILOptimizer/IPO/CMakeLists.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ target_sources(swiftSILOptimizer PRIVATE
44
ClosureSpecializer.cpp
55
CrossModuleSerializationSetup.cpp
66
DeadFunctionElimination.cpp
7-
EagerSpecializer.cpp
87
GlobalOpt.cpp
98
GlobalPropertyOpt.cpp
109
LetPropertiesOpts.cpp

lib/SILOptimizer/Transforms/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ target_sources(swiftSILOptimizer PRIVATE
1919
DestroyHoisting.cpp
2020
Devirtualizer.cpp
2121
DifferentiabilityWitnessDevirtualizer.cpp
22+
EagerSpecializer.cpp
2223
GenericSpecializer.cpp
2324
MergeCondFail.cpp
2425
Outliner.cpp

lib/SILOptimizer/IPO/EagerSpecializer.cpp renamed to lib/SILOptimizer/Transforms/EagerSpecializer.cpp

Lines changed: 66 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -738,7 +738,7 @@ SILValue EagerDispatch::emitArgumentConversion(
738738
namespace {
739739
// FIXME: This should be a function transform that pushes cloned functions on
740740
// the pass manager worklist.
741-
class EagerSpecializerTransform : public SILModuleTransform {
741+
class EagerSpecializerTransform : public SILFunctionTransform {
742742
public:
743743
EagerSpecializerTransform() {}
744744

@@ -751,7 +751,10 @@ class EagerSpecializerTransform : public SILModuleTransform {
751751
static SILFunction *eagerSpecialize(SILOptFunctionBuilder &FuncBuilder,
752752
SILFunction *GenericFunc,
753753
const SILSpecializeAttr &SA,
754-
const ReabstractionInfo &ReInfo) {
754+
const ReabstractionInfo &ReInfo,
755+
SmallVectorImpl<SILFunction *> &newFunctions) {
756+
assert(ReInfo.getSpecializedType());
757+
755758
LLVM_DEBUG(llvm::dbgs() << "Specializing " << GenericFunc->getName() << "\n");
756759

757760
LLVM_DEBUG(auto FT = GenericFunc->getLoweredFunctionType();
@@ -767,7 +770,13 @@ static SILFunction *eagerSpecialize(SILOptFunctionBuilder &FuncBuilder,
767770
ReInfo.getClonerParamSubstitutionMap(),
768771
ReInfo);
769772

770-
SILFunction *NewFunc = FuncSpecializer.trySpecialization();
773+
SILFunction *NewFunc = FuncSpecializer.lookupSpecialization();
774+
if (!NewFunc) {
775+
NewFunc = FuncSpecializer.tryCreateSpecialization();
776+
if (NewFunc)
777+
newFunctions.push_back(NewFunc);
778+
}
779+
771780
if (!NewFunc)
772781
LLVM_DEBUG(llvm::dbgs() << " Failed. Cannot specialize function.\n");
773782
return NewFunc;
@@ -779,64 +788,69 @@ void EagerSpecializerTransform::run() {
779788
return;
780789

781790
SILOptFunctionBuilder FuncBuilder(*this);
791+
auto &F = *getFunction();
782792

783793
// Process functions in any order.
784-
for (auto &F : *getModule()) {
785-
if (!F.shouldOptimize()) {
786-
LLVM_DEBUG(llvm::dbgs() << " Cannot specialize function " << F.getName()
787-
<< " because it is marked to be "
788-
"excluded from optimizations.\n");
789-
continue;
790-
}
791-
792-
// Only specialize functions in their home module.
793-
if (F.isExternalDeclaration() || F.isAvailableExternally())
794-
continue;
794+
if (!F.shouldOptimize()) {
795+
LLVM_DEBUG(llvm::dbgs() << " Cannot specialize function " << F.getName()
796+
<< " because it is marked to be "
797+
"excluded from optimizations.\n");
798+
return;
799+
}
795800

796-
if (F.isDynamicallyReplaceable())
797-
continue;
801+
// Only specialize functions in their home module.
802+
if (F.isExternalDeclaration() || F.isAvailableExternally())
803+
return;
798804

799-
if (!F.getLoweredFunctionType()->getInvocationGenericSignature())
800-
continue;
805+
if (F.isDynamicallyReplaceable())
806+
return;
801807

802-
// Create a specialized function with ReabstractionInfo for each attribute.
803-
SmallVector<SILFunction *, 8> SpecializedFuncs;
804-
SmallVector<ReabstractionInfo, 4> ReInfoVec;
805-
ReInfoVec.reserve(F.getSpecializeAttrs().size());
808+
if (!F.getLoweredFunctionType()->getInvocationGenericSignature())
809+
return;
806810

807-
// TODO: Use a decision-tree to reduce the amount of dynamic checks being
808-
// performed.
809-
for (auto *SA : F.getSpecializeAttrs()) {
810-
ReInfoVec.emplace_back(FuncBuilder.getModule().getSwiftModule(),
811-
FuncBuilder.getModule().isWholeModule(), &F,
812-
SA->getSpecializedSignature());
813-
auto *NewFunc = eagerSpecialize(FuncBuilder, &F, *SA, ReInfoVec.back());
811+
// Create a specialized function with ReabstractionInfo for each attribute.
812+
SmallVector<SILFunction *, 8> SpecializedFuncs;
813+
SmallVector<ReabstractionInfo, 4> ReInfoVec;
814+
ReInfoVec.reserve(F.getSpecializeAttrs().size());
815+
SmallVector<SILFunction *, 8> newFunctions;
816+
817+
// TODO: Use a decision-tree to reduce the amount of dynamic checks being
818+
// performed.
819+
for (auto *SA : F.getSpecializeAttrs()) {
820+
ReInfoVec.emplace_back(FuncBuilder.getModule().getSwiftModule(),
821+
FuncBuilder.getModule().isWholeModule(), &F,
822+
SA->getSpecializedSignature());
823+
auto *NewFunc =
824+
eagerSpecialize(FuncBuilder, &F, *SA, ReInfoVec.back(), newFunctions);
825+
826+
SpecializedFuncs.push_back(NewFunc);
827+
}
814828

815-
SpecializedFuncs.push_back(NewFunc);
816-
}
829+
// TODO: Optimize the dispatch code to minimize the amount
830+
// of checks. Use decision trees for this purpose.
831+
bool Changed = false;
832+
for_each3(F.getSpecializeAttrs(), SpecializedFuncs, ReInfoVec,
833+
[&](const SILSpecializeAttr *SA, SILFunction *NewFunc,
834+
const ReabstractionInfo &ReInfo) {
835+
if (NewFunc) {
836+
NewFunc->verify();
837+
Changed = true;
838+
EagerDispatch(&F, ReInfo).emitDispatchTo(NewFunc);
839+
}
840+
});
841+
842+
// Invalidate everything since we delete calls as well as add new
843+
// calls and branches.
844+
if (Changed) {
845+
invalidateAnalysis(SILAnalysis::InvalidationKind::Everything);
846+
}
817847

818-
// TODO: Optimize the dispatch code to minimize the amount
819-
// of checks. Use decision trees for this purpose.
820-
bool Changed = false;
821-
for_each3(F.getSpecializeAttrs(), SpecializedFuncs, ReInfoVec,
822-
[&](const SILSpecializeAttr *SA, SILFunction *NewFunc,
823-
const ReabstractionInfo &ReInfo) {
824-
if (NewFunc) {
825-
NewFunc->verify();
826-
Changed = true;
827-
EagerDispatch(&F, ReInfo).emitDispatchTo(NewFunc);
828-
}
829-
});
830-
831-
// Invalidate everything since we delete calls as well as add new
832-
// calls and branches.
833-
if (Changed) {
834-
invalidateAnalysis(&F, SILAnalysis::InvalidationKind::Everything);
835-
}
848+
// As specializations are created, the attributes should be removed.
849+
F.clearSpecializeAttrs();
850+
F.verify();
836851

837-
// As specializations are created, the attributes should be removed.
838-
F.clearSpecializeAttrs();
839-
F.verify();
852+
for (SILFunction *newF : newFunctions) {
853+
addFunctionToPassManagerWorklist(newF, nullptr);
840854
}
841855
}
842856

test/ModuleInterface/optimization-level.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
// optimization passes don't run when compiling a .swiftinterface that was
1111
// generated with -Onone.
1212

13-
// OPT: EagerSpecializer
14-
// UNOPT-NOT: EagerSpecializer
13+
// OPT: GlobalOpt
14+
// UNOPT-NOT: GlobalOpt
1515
public func f() {}
1616

0 commit comments

Comments
 (0)