Skip to content

Commit 401a2ac

Browse files
authored
Merge pull request #84704 from eeckstein/closure-specialization
ClosureSpecialization: support for OSSA and a big overhaul
2 parents 9883477 + 8efafc7 commit 401a2ac

File tree

53 files changed

+1923
-2923
lines changed

Some content is hidden

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

53 files changed

+1923
-2923
lines changed

SwiftCompilerSources/Sources/Optimizer/FunctionPasses/ClosureSpecialization.swift

Lines changed: 512 additions & 1195 deletions
Large diffs are not rendered by default.

SwiftCompilerSources/Sources/Optimizer/FunctionPasses/ConstantCapturePropagation.swift

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ private func constantPropagateCaptures(of partialApply: PartialApplyInst, _ cont
112112
// Escaping closures consume their arguments. Therefore we need to destroy the removed argument values.
113113
addCompensatingDestroys(for: constArgs, context)
114114
}
115-
let newArguments = nonConstArgs.map { $0.value }
115+
let newArguments = Array(nonConstArgs.values)
116116
rewritePartialApply(partialApply, withSpecialized: specializedCallee, arguments: newArguments, context)
117117
}
118118

@@ -195,8 +195,7 @@ private func cloneArgument(_ argumentOp: Operand,
195195
if partialApply.calleeArgumentConventions[calleeArgIdx].isGuaranteed {
196196
// If the original argument was passed as guaranteed, i.e. is _not_ destroyed in the closure, we have
197197
// to destroy the cloned argument at function exits.
198-
for block in targetFunction.blocks where block.terminator.isFunctionExiting {
199-
let builder = Builder(before: block.terminator, context)
198+
Builder.insertCleanupAtFunctionExits(of: targetFunction, context) { builder in
200199
builder.emitDestroy(of: clonedArg)
201200
}
202201
}

SwiftCompilerSources/Sources/Optimizer/FunctionPasses/InitializeStaticGlobals.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -404,7 +404,7 @@ private extension Value {
404404
case is LoadInst:
405405
return true
406406
case is StructInst, is TupleInst:
407-
worklist.pushIfNotVisited(contentsOf: (v as! Instruction).operands.lazy.map { $0.value })
407+
worklist.pushIfNotVisited(contentsOf: (v as! Instruction).operands.values)
408408
case let ei as EnumInst:
409409
if let payload = ei.payload {
410410
worklist.pushIfNotVisited(payload)

SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyCondBranch.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,9 @@ private extension CondBranchInst {
2727
}
2828
let builder = Builder(before: self, context)
2929
if conditionValue == 0 {
30-
builder.createBranch(to: falseBlock, arguments: Array(falseOperands.map { $0.value }))
30+
builder.createBranch(to: falseBlock, arguments: Array(falseOperands.values))
3131
} else {
32-
builder.createBranch(to: trueBlock, arguments: Array(trueOperands.map { $0.value }))
32+
builder.createBranch(to: trueBlock, arguments: Array(trueOperands.values))
3333
}
3434
context.erase(instruction: self)
3535
}

SwiftCompilerSources/Sources/Optimizer/ModulePasses/StackProtection.swift

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -339,13 +339,9 @@ private struct StackProtectionOptimization {
339339

340340
builder.createCopyAddr(from: argument, to: temporary, takeSource: true, initializeDest: true)
341341

342-
for block in function.blocks {
343-
let terminator = block.terminator
344-
if terminator.isFunctionExiting {
345-
let exitBuilder = Builder(before: terminator, location: terminator.location.asAutoGenerated, context)
346-
exitBuilder.createCopyAddr(from: temporary, to: argument, takeSource: true, initializeDest: true)
347-
exitBuilder.createDeallocStack(temporary)
348-
}
342+
Builder.insertCleanupAtFunctionExits(of: function, context) { builder in
343+
builder.createCopyAddr(from: temporary, to: argument, takeSource: true, initializeDest: true)
344+
builder.createDeallocStack(temporary)
349345
}
350346
log("move addr protection in \(function.name): \(argument)")
351347

SwiftCompilerSources/Sources/Optimizer/PassManager/FunctionPassContext.swift

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,10 +111,34 @@ struct FunctionPassContext : MutatingContext {
111111
return String(taking: bridgedPassContext.mangleOutlinedVariable(function.bridged))
112112
}
113113

114-
func mangle(withClosureArguments closureArgs: [(argumentIndex: Int, argumentValue: Value)],
114+
enum ClosureArgumentMangling {
115+
case closure(SingleValueInstruction)
116+
117+
/// The argument specializes for the same closure as a previous argument, e.g.
118+
/// ```
119+
/// %1 = partial_apply %closure
120+
/// apply %f(%1, %1) // first argument: `.closure(%1)`
121+
/// // second argument: `.previousArgumentIndex(0)`
122+
case previousArgumentIndex(Int)
123+
}
124+
125+
func mangle(withClosureArguments closureArgs: [(argumentIndex: Int, argumentValue: ClosureArgumentMangling)],
115126
from applySiteCallee: Function
116127
) -> String {
117-
closureArgs.withBridgedArrayRef{ bridgedClosureArgs in
128+
let bridgedArgManglings = closureArgs.map {
129+
switch $0.argumentValue {
130+
case .closure(let closure):
131+
return BridgedPassContext.ClosureArgMangling(argIdx: $0.argumentIndex,
132+
inst: Optional<Instruction>(closure).bridged,
133+
otherArgIdx: -1)
134+
case .previousArgumentIndex(let idx):
135+
return BridgedPassContext.ClosureArgMangling(argIdx: $0.argumentIndex,
136+
inst: OptionalBridgedInstruction(),
137+
otherArgIdx: idx)
138+
}
139+
}
140+
141+
return bridgedArgManglings.withBridgedArrayRef{ bridgedClosureArgs in
118142
String(taking: bridgedPassContext.mangleWithClosureArgs(bridgedClosureArgs, applySiteCallee.bridged))
119143
}
120144
}

SwiftCompilerSources/Sources/Optimizer/PassManager/PassRegistration.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ private func registerSwiftPasses() {
105105
registerPass(tempRValueElimination, { tempRValueElimination.run($0) })
106106
registerPass(mandatoryTempRValueElimination, { mandatoryTempRValueElimination.run($0) })
107107
registerPass(tempLValueElimination, { tempLValueElimination.run($0) })
108-
registerPass(generalClosureSpecialization, { generalClosureSpecialization.run($0) })
108+
registerPass(closureSpecialization, { closureSpecialization.run($0) })
109109
registerPass(autodiffClosureSpecialization, { autodiffClosureSpecialization.run($0) })
110110
registerPass(loopInvariantCodeMotionPass, { loopInvariantCodeMotionPass.run($0) })
111111

SwiftCompilerSources/Sources/Optimizer/Utilities/FunctionTest.swift

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ public func registerOptimizerTests() {
4343
registerFunctionTests(
4444
addressOwnershipLiveRangeTest,
4545
argumentConventionsTest,
46-
getPullbackClosureInfoTest,
4746
interiorLivenessTest,
4847
lifetimeDependenceRootTest,
4948
lifetimeDependenceScopeTest,
@@ -52,8 +51,6 @@ public func registerOptimizerTests() {
5251
localVariableReachableUsesTest,
5352
localVariableReachingAssignmentsTest,
5453
rangeOverlapsPathTest,
55-
rewrittenCallerBodyTest,
56-
specializedFunctionSignatureAndBodyTest,
5754
variableIntroducerTest
5855
)
5956

SwiftCompilerSources/Sources/Optimizer/Utilities/OptUtils.swift

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ extension Value {
7171
}
7272
switch v {
7373
case let fw as ForwardingInstruction:
74-
worklist.pushIfNotVisited(contentsOf: fw.definedOperands.lazy.map { $0.value })
74+
worklist.pushIfNotVisited(contentsOf: fw.definedOperands.values)
7575
case let bf as BorrowedFromInst:
7676
worklist.pushIfNotVisited(bf.borrowedValue)
7777
case let bb as BeginBorrowInst:
@@ -82,7 +82,7 @@ extension Value {
8282
} else if let termResult = TerminatorResult(arg),
8383
let fw = termResult.terminator as? ForwardingInstruction
8484
{
85-
worklist.pushIfNotVisited(contentsOf: fw.definedOperands.lazy.map { $0.value })
85+
worklist.pushIfNotVisited(contentsOf: fw.definedOperands.values)
8686
}
8787
default:
8888
continue
@@ -262,6 +262,18 @@ extension Builder {
262262
}
263263
}
264264

265+
static func insertCleanupAtFunctionExits(
266+
of function: Function,
267+
_ context: some MutatingContext,
268+
insert: (Builder) -> ()
269+
) {
270+
for exitBlock in function.blocks where exitBlock.terminator.isFunctionExiting {
271+
let terminator = exitBlock.terminator
272+
let builder = Builder(before: terminator, location: terminator.location.asCleanup, context)
273+
insert(builder)
274+
}
275+
}
276+
265277
func destroyCapturedArgs(for paiOnStack: PartialApplyInst) {
266278
precondition(paiOnStack.isOnStack, "Function must only be called for `partial_apply`s on stack!")
267279
self.bridged.destroyCapturedArgs(paiOnStack.bridged)

SwiftCompilerSources/Sources/SIL/Argument.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ public struct Phi {
170170
}
171171

172172
public var incomingValues: LazyMapSequence<LazyMapSequence<PredecessorList, Operand>, Value> {
173-
incomingOperands.lazy.map { $0.value }
173+
incomingOperands.values
174174
}
175175

176176
public var isReborrow: Bool { value.isReborrow }

0 commit comments

Comments
 (0)