Skip to content

Commit fd60984

Browse files
committed
Makes the swift-based closure-spec pass an experimental frontend feature
1 parent c8375c0 commit fd60984

File tree

9 files changed

+59
-10
lines changed

9 files changed

+59
-10
lines changed

SwiftCompilerSources/Sources/Optimizer/FunctionPasses/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ swift_compiler_sources(Optimizer
1212
AsyncDemotion.swift
1313
BooleanLiteralFolding.swift
1414
CleanupDebugSteps.swift
15+
ClosureSpecialization.swift
1516
ComputeEscapeEffects.swift
1617
ComputeSideEffects.swift
1718
DeadStoreElimination.swift
@@ -30,5 +31,4 @@ swift_compiler_sources(Optimizer
3031
SimplificationPasses.swift
3132
StackPromotion.swift
3233
StripObjectHeaders.swift
33-
AutodiffClosureSpecialization.swift
3434
)

SwiftCompilerSources/Sources/Optimizer/FunctionPasses/AutodiffClosureSpecialization.swift renamed to SwiftCompilerSources/Sources/Optimizer/FunctionPasses/ClosureSpecialization.swift

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//===--- AutodiffClosureSpecialization.swift ---------------------------===//
1+
//===--- ClosureSpecialization.swift ---------------------------===//
22
//
33
// This source file is part of the Swift.org open source project
44
//
@@ -10,8 +10,14 @@
1010
//
1111
//===-----------------------------------------------------------------------===//
1212

13+
/// This file contains the closure-specialization optimizations for general and differentiable Swift.
14+
15+
/// General Closure Specialization
16+
/// ------------------------------------
17+
/// TODO: Add description when the functionality is added.
18+
1319
/// AutoDiff Closure Specialization
14-
/// ----------------------
20+
/// -------------------------------
1521
/// This optimization performs closure specialization tailored for the patterns seen in Swift Autodiff. In principle,
1622
/// the optimization does the same thing as the existing closure specialization pass. However, it is tailored to the
1723
/// patterns of Swift Autodiff.
@@ -100,12 +106,32 @@ private func log(_ message: @autoclosure () -> String) {
100106
}
101107

102108
// =========== Entry point =========== //
103-
let autodiffClosureSpecialization = FunctionPass(name: "autodiff-closure-specialize") {
109+
let generalClosureSpecialization = FunctionPass(name: "experimental-swift-based-closure-specialization") {
110+
(function: Function, context: FunctionPassContext) in
111+
// TODO: Implement general closure specialization optimization
112+
print("NOT IMPLEMENTED")
113+
}
114+
115+
let autodiffClosureSpecialization = FunctionPass(name: "autodiff-closure-specialization") {
104116
(function: Function, context: FunctionPassContext) in
105117
// TODO: Pass is a WIP and current implementation is incomplete
106118
if !function.isAutodiffVJP {
107119
return
108120
}
121+
122+
print("Specializing closures in function: \(function.name)")
123+
print("===============================================")
124+
var callSites = gatherCallSites(in: function, context)
125+
126+
callSites.forEach { callSite in
127+
print("PartialApply call site: \(callSite.applySite)")
128+
print("Passed in closures: ")
129+
for index in callSite.closureArgDescriptors.indices {
130+
var closureArgDescriptor = callSite.closureArgDescriptors[index]
131+
print("\(index+1). \(closureArgDescriptor.closureInfo.closure)")
132+
}
133+
}
134+
print("\n")
109135
}
110136

111137
// =========== Top-level functions ========== //
@@ -276,8 +302,8 @@ private func handleNonApplies(for rootClosure: SingleValueInstruction,
276302
if !pai.isPullbackInResultOfAutodiffVJP,
277303
pai.isPartialApplyOfReabstractionThunk,
278304
pai.isSupportedClosure,
279-
pai.callee.type.isNoEscapeFunction,
280-
pai.callee.type.isThickFunction
305+
pai.arguments[0].type.isNoEscapeFunction,
306+
pai.arguments[0].type.isThickFunction
281307
{
282308
rootClosureConversionsAndReabstractions.pushIfNotVisited(contentsOf: pai.uses)
283309
possibleMarkDependenceBases.insert(pai)
@@ -338,6 +364,7 @@ private func handleApplies(for rootClosure: SingleValueInstruction, callSiteMap:
338364
continue
339365
}
340366

367+
// TODO: Handling generic closures may be possible but is not yet implemented
341368
if pai.hasSubstitutions || !pai.calleeIsDynamicFunctionRef || !pai.isPullbackInResultOfAutodiffVJP {
342369
continue
343370
}
@@ -507,7 +534,7 @@ private func markConvertedAndReabstractedClosuresAsUsed(rootClosure: Value, conv
507534
convertedAndReabstractedClosures.insert(pai)
508535
return
509536
markConvertedAndReabstractedClosuresAsUsed(rootClosure: rootClosure,
510-
convertedAndReabstractedClosure: pai.callee,
537+
convertedAndReabstractedClosure: pai.arguments[0],
511538
convertedAndReabstractedClosures: &convertedAndReabstractedClosures)
512539
case let cvt as ConvertFunctionInst:
513540
convertedAndReabstractedClosures.insert(cvt)

SwiftCompilerSources/Sources/Optimizer/PassManager/PassRegistration.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ private func registerSwiftPasses() {
9393
registerPass(lifetimeDependenceDiagnosticsPass, { lifetimeDependenceDiagnosticsPass.run($0) })
9494
registerPass(lifetimeDependenceInsertionPass, { lifetimeDependenceInsertionPass.run($0) })
9595
registerPass(lifetimeDependenceScopeFixupPass, { lifetimeDependenceScopeFixupPass.run($0) })
96+
registerPass(generalClosureSpecialization, { generalClosureSpecialization.run($0) })
9697
registerPass(autodiffClosureSpecialization, { autodiffClosureSpecialization.run($0) })
9798

9899
// Instruction passes

SwiftCompilerSources/Sources/Optimizer/Utilities/OptUtils.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -405,7 +405,8 @@ extension PartialApplyInst {
405405
if self.numArguments == 1 || self.numArguments == 2,
406406
let fun = self.referencedFunction,
407407
fun.isReabstractionThunk,
408-
self.callee.type.isReferenceCounted(in: self.parentFunction) || self.callee.type.isThickFunction
408+
self.arguments[0].type.isFunction,
409+
self.arguments[0].type.isReferenceCounted(in: self.parentFunction) || self.callee.type.isThickFunction
409410
{
410411
return true
411412
}

include/swift/AST/SILOptions.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,10 @@ class SILOptions {
290290
/// Are we building in embedded Swift + -no-allocations?
291291
bool NoAllocations = false;
292292

293+
/// Should we use the experimental Swift based closure-specialization
294+
/// optimization pass instead of the existing C++ one.
295+
bool EnableExperimentalSwiftBasedClosureSpecialization = false;
296+
293297
/// The name of the file to which the backend should save optimization
294298
/// records.
295299
std::string OptRecordFile;

include/swift/Option/FrontendOptions.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,10 @@ def enable_experimental_async_top_level :
359359
// HIDDEN FLAGS
360360
let Flags = [FrontendOption, NoDriverOption, HelpHidden] in {
361361

362+
def enable_experimental_swift_based_closure_specialization :
363+
Flag<["-"], "experimental-swift-based-closure-specialization">,
364+
HelpText<"Use the experimental Swift based closure-specialization optimization pass instead of the existing C++ one">;
365+
362366
def checked_async_objc_bridging : Joined<["-"], "checked-async-objc-bridging=">,
363367
HelpText<"Control whether checked continuations are used when bridging "
364368
"async calls from Swift to ObjC: 'on', 'off' ">;

include/swift/SILOptimizer/PassManager/Passes.def

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,8 +146,13 @@ PASS(CapturePropagation, "capture-prop",
146146
"Captured Constant Propagation")
147147
PASS(ClosureSpecializer, "closure-specialize",
148148
"Closure Specialization on Constant Function Arguments")
149-
SWIFT_FUNCTION_PASS(AutodiffClosureSpecialization, "autodiff-closure-specialize",
149+
150+
// NOTE - ExperimentalSwiftBasedClosureSpecialization and AutodiffClosureSpecialization are a WIP
151+
SWIFT_FUNCTION_PASS(ExperimentalSwiftBasedClosureSpecialization, "experimental-swift-based-closure-specialization",
152+
"General closure-specialization pass written in Swift")
153+
SWIFT_FUNCTION_PASS(AutodiffClosureSpecialization, "autodiff-closure-specialization",
150154
"Autodiff specific closure-specialization pass")
155+
151156
PASS(ClosureLifetimeFixup, "closure-lifetime-fixup",
152157
"Closure Lifetime Fixup")
153158
PASS(CodeSinking, "code-sinking",

lib/Frontend/CompilerInvocation.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2609,6 +2609,9 @@ static bool ParseSILArgs(SILOptions &Opts, ArgList &Args,
26092609

26102610
Opts.NoAllocations = Args.hasArg(OPT_no_allocations);
26112611

2612+
Opts.EnableExperimentalSwiftBasedClosureSpecialization =
2613+
Args.hasArg(OPT_enable_experimental_swift_based_closure_specialization);
2614+
26122615
return false;
26132616
}
26142617

lib/SILOptimizer/PassManager/PassPipeline.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -768,7 +768,11 @@ static void addMidLevelFunctionPipeline(SILPassPipelinePlan &P) {
768768
P.addCapturePropagation();
769769

770770
// Specialize closure.
771-
P.addClosureSpecializer();
771+
if (P.getOptions().EnableExperimentalSwiftBasedClosureSpecialization) {
772+
P.addExperimentalSwiftBasedClosureSpecialization();
773+
} else {
774+
P.addClosureSpecializer();
775+
}
772776

773777
// Do the second stack promotion on low-level SIL.
774778
P.addStackPromotion();

0 commit comments

Comments
 (0)