Skip to content

Commit ad67883

Browse files
committed
Swift SIL: some improvements for WalkUtils and EscapeInfo
* "merge" the `Path` and `State` in WalkUtils into a single `WalkingPath`. This makes it simpler for clients to configure a path and additional state variables. EscapeInfo now defines `EscapePath` which includes the projection path and EscapeInfo's specific state variables. * Make the `WalkerCache` part of the WalkUtils, so that not all clients have to re-implement it. * Rename `walkDownResults` -> `walkDownAllResults` and `walkUpOperands` -> `walkUpAllOperands` and make these functions client configurable.
1 parent ab4fa0a commit ad67883

File tree

6 files changed

+470
-427
lines changed

6 files changed

+470
-427
lines changed

SwiftCompilerSources/Sources/Optimizer/FunctionPasses/ComputeEffects.swift

Lines changed: 27 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
import SIL
1414

1515
fileprivate typealias Selection = ArgumentEffect.Selection
16-
fileprivate typealias Path = ArgumentEffect.Path
1716

1817
/// Computes effects for function arguments.
1918
///
@@ -34,7 +33,7 @@ let computeEffects = FunctionPass(name: "compute-effects", {
3433
var argsWithDefinedEffects = getArgIndicesWithDefinedEffects(of: function)
3534

3635
struct IgnoreRecursiveCallVisitor : EscapeInfoVisitor {
37-
func visitUse(operand: Operand, path: Path, state: State) -> UseResult {
36+
func visitUse(operand: Operand, path: EscapePath) -> UseResult {
3837
return isOperandOfRecursiveCall(operand) ? .ignore : .continueWalk
3938
}
4039
}
@@ -50,17 +49,17 @@ let computeEffects = FunctionPass(name: "compute-effects", {
5049
if argsWithDefinedEffects.contains(arg.index) { continue }
5150

5251
// First check: is the argument (or a projected value of it) escaping at all?
53-
if !escapeInfo.isEscapingWhenWalkingDown(object: arg, path: Path(.anything)) {
54-
let selectedArg = Selection(arg, pathPattern: Path(.anything))
52+
if !escapeInfo.isEscapingWhenWalkingDown(object: arg, path: SmallProjectionPath(.anything)) {
53+
let selectedArg = Selection(arg, pathPattern: SmallProjectionPath(.anything))
5554
newEffects.push(ArgumentEffect(.notEscaping, selectedArg: selectedArg))
5655
continue
5756
}
5857

5958
// Now compute effects for two important cases:
6059
// * the argument itself + any value projections, and...
61-
if addArgEffects(context: context, arg, argPath: Path(), to: &newEffects, returnInst) {
60+
if addArgEffects(context: context, arg, argPath: SmallProjectionPath(), to: &newEffects, returnInst) {
6261
// * single class indirections
63-
_ = addArgEffects(context: context, arg, argPath: Path(.anyValueFields).push(.anyClassField),
62+
_ = addArgEffects(context: context, arg, argPath: SmallProjectionPath(.anyValueFields).push(.anyClassField),
6463
to: &newEffects, returnInst)
6564
}
6665
}
@@ -75,7 +74,7 @@ let computeEffects = FunctionPass(name: "compute-effects", {
7574

7675
/// Returns true if an argument effect was added.
7776
private
78-
func addArgEffects(context: PassContext, _ arg: FunctionArgument, argPath ap: Path,
77+
func addArgEffects(context: PassContext, _ arg: FunctionArgument, argPath ap: SmallProjectionPath,
7978
to newEffects: inout Stack<ArgumentEffect>,
8079
_ returnInst: ReturnInst?) -> Bool {
8180
// Correct the path if the argument is not a class reference itself, but a value type
@@ -91,18 +90,18 @@ func addArgEffects(context: PassContext, _ arg: FunctionArgument, argPath ap: Pa
9190
var toSelection: Selection?
9291
var returnInst: ReturnInst?
9392

94-
mutating func visitUse(operand: Operand, path: Path, state: State) -> UseResult {
93+
mutating func visitUse(operand: Operand, path: EscapePath) -> UseResult {
9594
if operand.instruction == returnInst {
9695
// The argument escapes to the function return
97-
if state.followStores {
96+
if path.followStores {
9897
// The escaping path must not introduce a followStores.
9998
return .abort
10099
}
101100
if let ta = toSelection {
102101
if ta.value != .returnValue { return .abort }
103-
toSelection = Selection(.returnValue, pathPattern: path.merge(with: ta.pathPattern))
102+
toSelection = Selection(.returnValue, pathPattern: path.projectionPath.merge(with: ta.pathPattern))
104103
} else {
105-
toSelection = Selection(.returnValue, pathPattern: path)
104+
toSelection = Selection(.returnValue, pathPattern: path.projectionPath)
106105
}
107106
return .ignore
108107
}
@@ -112,21 +111,21 @@ func addArgEffects(context: PassContext, _ arg: FunctionArgument, argPath ap: Pa
112111
return .continueWalk
113112
}
114113

115-
mutating func visitDef(def: Value, path: Path, state: State) -> DefResult {
114+
mutating func visitDef(def: Value, path: EscapePath) -> DefResult {
116115
guard let destArg = def as? FunctionArgument else {
117116
return .continueWalkUp
118117
}
119118
// The argument escapes to another argument (e.g. an out or inout argument)
120-
if state.followStores {
119+
if path.followStores {
121120
// The escaping path must not introduce a followStores.
122121
return .abort
123122
}
124123
let argIdx = destArg.index
125124
if let ta = toSelection {
126125
if ta.value != .argument(argIdx) { return .abort }
127-
toSelection = Selection(.argument(argIdx), pathPattern: path.merge(with: ta.pathPattern))
126+
toSelection = Selection(.argument(argIdx), pathPattern: path.projectionPath.merge(with: ta.pathPattern))
128127
} else {
129-
toSelection = Selection(.argument(argIdx), pathPattern: path)
128+
toSelection = Selection(.argument(argIdx), pathPattern: path.projectionPath)
130129
}
131130
return .walkDown
132131
}
@@ -197,7 +196,7 @@ private func isOperandOfRecursiveCall(_ op: Operand) -> Bool {
197196
/// there are no other arguments or escape points than `fromArgument`. Also, the
198197
/// path at the `fromArgument` must match with `fromPath`.
199198
private
200-
func isExclusiveEscape(context: PassContext, fromArgument: Argument, fromPath: Path, to toSelection: Selection,
199+
func isExclusiveEscape(context: PassContext, fromArgument: Argument, fromPath: SmallProjectionPath, to toSelection: Selection,
201200
_ returnInst: ReturnInst) -> Bool {
202201
switch toSelection.value {
203202

@@ -207,25 +206,25 @@ func isExclusiveEscape(context: PassContext, fromArgument: Argument, fromPath: P
207206
let fromArgument: Argument
208207
let toSelection: Selection
209208
let returnInst: ReturnInst
210-
let fromPath: Path
209+
let fromPath: SmallProjectionPath
211210

212-
mutating func visitUse(operand: Operand, path: Path, state: State) -> UseResult {
211+
mutating func visitUse(operand: Operand, path: EscapePath) -> UseResult {
213212
if operand.instruction == returnInst {
214-
if state.followStores { return .abort }
215-
if path.matches(pattern: toSelection.pathPattern) {
213+
if path.followStores { return .abort }
214+
if path.projectionPath.matches(pattern: toSelection.pathPattern) {
216215
return .ignore
217216
}
218217
return .abort
219218
}
220219
return .continueWalk
221220
}
222221

223-
mutating func visitDef(def: Value, path: Path, state: State) -> DefResult {
222+
mutating func visitDef(def: Value, path: EscapePath) -> DefResult {
224223
guard let arg = def as? FunctionArgument else {
225224
return .continueWalkUp
226225
}
227-
if state.followStores { return .abort }
228-
if arg == fromArgument && path.matches(pattern: fromPath) {
226+
if path.followStores { return .abort }
227+
if arg == fromArgument && path.projectionPath.matches(pattern: fromPath) {
229228
return .walkDown
230229
}
231230
return .abort
@@ -240,17 +239,17 @@ func isExclusiveEscape(context: PassContext, fromArgument: Argument, fromPath: P
240239
case .argument(let toArgIdx):
241240
struct IsExclusiveArgumentEscapeVisitor : EscapeInfoVisitor {
242241
let fromArgument: Argument
243-
let fromPath: Path
242+
let fromPath: SmallProjectionPath
244243
let toSelection: Selection
245244
let toArg: FunctionArgument
246245

247-
mutating func visitDef(def: Value, path: Path, state: State) -> DefResult {
246+
mutating func visitDef(def: Value, path: EscapePath) -> DefResult {
248247
guard let arg = def as? FunctionArgument else {
249248
return .continueWalkUp
250249
}
251-
if state.followStores { return .abort }
252-
if arg == fromArgument && path.matches(pattern: fromPath) { return .walkDown }
253-
if arg == toArg && path.matches(pattern: toSelection.pathPattern) { return .walkDown }
250+
if path.followStores { return .abort }
251+
if arg == fromArgument && path.projectionPath.matches(pattern: fromPath) { return .walkDown }
252+
if arg == toArg && path.projectionPath.matches(pattern: toSelection.pathPattern) { return .walkDown }
254253
return .abort
255254
}
256255
}

SwiftCompilerSources/Sources/Optimizer/FunctionPasses/EscapeInfoDumper.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,19 +25,19 @@ let escapeInfoDumper = FunctionPass(name: "dump-escape-info", {
2525
struct Visitor : EscapeInfoVisitor {
2626
var results: Set<String> = Set()
2727

28-
mutating func visitUse(operand: Operand, path: Path, state: State) -> UseResult {
28+
mutating func visitUse(operand: Operand, path: EscapePath) -> UseResult {
2929
if operand.instruction is ReturnInst {
30-
results.insert("return[\(path)]")
30+
results.insert("return[\(path.projectionPath)]")
3131
return .ignore
3232
}
3333
return .continueWalk
3434
}
3535

36-
mutating func visitDef(def: Value, path: Path, state: State) -> DefResult {
36+
mutating func visitDef(def: Value, path: EscapePath) -> DefResult {
3737
guard let arg = def as? FunctionArgument else {
3838
return .continueWalkUp
3939
}
40-
results.insert("arg\(arg.index)[\(path)]")
40+
results.insert("arg\(arg.index)[\(path.projectionPath)]")
4141
return .walkDown
4242
}
4343
}
@@ -96,7 +96,7 @@ let addressEscapeInfoDumper = FunctionPass(name: "dump-addr-escape-info", {
9696

9797
struct Visitor : EscapeInfoVisitor {
9898
let apply: Instruction
99-
mutating func visitUse(operand: Operand, path: Path, state: State) -> UseResult {
99+
mutating func visitUse(operand: Operand, path: EscapePath) -> UseResult {
100100
let user = operand.instruction
101101
if user == apply {
102102
return .abort

SwiftCompilerSources/Sources/Optimizer/FunctionPasses/StackPromotion.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ private func getDominatingBlockOfAllUsePoints(context: PassContext,
201201
struct Visitor : EscapeInfoVisitor {
202202
var dominatingBlock: BasicBlock
203203
let domTree: DominatorTree
204-
mutating func visitUse(operand: Operand, path: Path, state: State) -> UseResult {
204+
mutating func visitUse(operand: Operand, path: EscapePath) -> UseResult {
205205
let defBlock = operand.value.definingBlock
206206
if defBlock.dominates(dominatingBlock, domTree) {
207207
dominatingBlock = defBlock
@@ -232,7 +232,7 @@ func computeInnerAndOuterLiferanges(instruction: SingleValueInstruction, in domB
232232
self.domTree = domTree
233233
}
234234

235-
mutating func visitUse(operand: Operand, path: Path, state: State) -> UseResult {
235+
mutating func visitUse(operand: Operand, path: EscapePath) -> UseResult {
236236
let user = operand.instruction
237237
if innerRange.blockRange.begin.dominates(user.block, domTree) {
238238
innerRange.insert(user)

0 commit comments

Comments
 (0)