@@ -129,14 +129,18 @@ private struct GatherLifetimeIntroducers : ForwardingUseDefWalker {
129
129
130
130
enum ForwardingUseResult : CustomStringConvertible {
131
131
case operand( Operand )
132
- case deadValue( Value )
132
+ case deadValue( Value , Operand ? )
133
133
134
134
var description : String {
135
135
switch self {
136
136
case . operand( let operand) :
137
137
return operand. description
138
- case . deadValue( let deadValue) :
139
- return " dead value: " + deadValue. description
138
+ case . deadValue( let deadValue, let operand) :
139
+ var desc = " dead value: \( deadValue. description) "
140
+ if let operand = operand {
141
+ desc += " from: \( operand) "
142
+ }
143
+ return desc
140
144
}
141
145
}
142
146
}
@@ -146,25 +150,35 @@ protocol ForwardingDefUseWalker {
146
150
// Minimally, check a ValueSet. This walker may traverse chains of aggregation and destructuring by default. Implementations may handle phis.
147
151
mutating func needWalk( for value: Value ) -> Bool
148
152
153
+ mutating func leafUse( _ operand: Operand ) -> WalkResult
154
+
149
155
// Report any initial or forwarded with no uses. Only relevant for
150
156
// guaranteed values or incomplete OSSA. This could be a dead
151
157
// instruction, a terminator in which the result is dead on one
152
158
// path, or a dead phi.
153
- mutating func deadValue( _: Value ) -> WalkResult
159
+ //
160
+ // \p operand is nil if \p value is the root.
161
+ mutating func deadValue( _ value: Value , using operand: Operand ? ) -> WalkResult
154
162
155
- mutating func leafUse ( _ : Operand ) -> WalkResult
163
+ mutating func walkDown ( root : Value ) -> WalkResult
156
164
157
- mutating func walkDownUses( of: Value ) -> WalkResult
165
+ mutating func walkDownUses( of: Value , using : Operand ? ) -> WalkResult
158
166
159
167
mutating func walkDown( operand: Operand ) -> WalkResult
160
168
}
161
169
162
170
extension ForwardingDefUseWalker {
163
- mutating func walkDownUses( of value: Value ) -> WalkResult {
164
- return walkDownUsesDefault ( of: value)
171
+ mutating func walkDown( root: Value ) -> WalkResult {
172
+ walkDownUses ( of: root, using: nil )
173
+ }
174
+
175
+ mutating func walkDownUses( of value: Value , using operand: Operand ? )
176
+ -> WalkResult {
177
+ return walkDownUsesDefault ( of: value, using: operand)
165
178
}
166
179
167
- mutating func walkDownUsesDefault( of value: Value ) -> WalkResult {
180
+ mutating func walkDownUsesDefault( of value: Value , using operand: Operand ? )
181
+ -> WalkResult {
168
182
if !needWalk( for: value) { return . continueWalk }
169
183
170
184
var hasUse = false
@@ -175,7 +189,7 @@ extension ForwardingDefUseWalker {
175
189
hasUse = true
176
190
}
177
191
if !hasUse {
178
- deadValue ( value)
192
+ return deadValue ( value, using : operand )
179
193
}
180
194
return . continueWalk
181
195
}
@@ -186,18 +200,18 @@ extension ForwardingDefUseWalker {
186
200
187
201
mutating func walkDownDefault( operand: Operand ) -> WalkResult {
188
202
if let inst = operand. instruction as? ForwardingInstruction {
189
- return walkDownAllResults ( of: inst)
203
+ return walkDownAllResults ( of: inst, using : operand )
190
204
}
191
205
if let phi = Phi ( using: operand) {
192
- return walkDownUses ( of: phi. value)
206
+ return walkDownUses ( of: phi. value, using : operand )
193
207
}
194
208
return leafUse ( operand)
195
209
}
196
210
197
- private mutating func walkDownAllResults( of inst: ForwardingInstruction )
198
- -> WalkResult {
211
+ private mutating func walkDownAllResults( of inst: ForwardingInstruction ,
212
+ using operand : Operand ? ) -> WalkResult {
199
213
for result in inst. forwardedResults {
200
- if walkDownUses ( of: result) == . abortWalk {
214
+ if walkDownUses ( of: result, using : operand ) == . abortWalk {
201
215
return . abortWalk
202
216
}
203
217
}
@@ -213,7 +227,7 @@ func visitForwardedUses(introducer: Value, _ context: Context,
213
227
-> WalkResult {
214
228
var useVisitor = VisitForwardedUses ( visitor: visitor, context)
215
229
defer { useVisitor. visitedValues. deinitialize ( ) }
216
- return useVisitor. walkDownUses ( of : introducer)
230
+ return useVisitor. walkDown ( root : introducer)
217
231
}
218
232
219
233
private struct VisitForwardedUses : ForwardingDefUseWalker {
@@ -234,8 +248,9 @@ private struct VisitForwardedUses : ForwardingDefUseWalker {
234
248
return visitor ( . operand( operand) )
235
249
}
236
250
237
- mutating func deadValue( _ value: Value ) -> WalkResult {
238
- return visitor ( . deadValue( value) )
251
+ mutating func deadValue( _ value: Value , using operand: Operand ? )
252
+ -> WalkResult {
253
+ return visitor ( . deadValue( value, operand) )
239
254
}
240
255
}
241
256
@@ -250,8 +265,8 @@ let forwardingUseDefTest = FunctionTest("forwarding_use_def_test") {
250
265
let forwardingDefUseTest = FunctionTest ( " forwarding_def_use_test " ) {
251
266
function, arguments, context in
252
267
let value = arguments. takeValue ( )
253
- _ = visitForwardedUses ( introducer: value, context) { operand in
254
- print ( " USE: \( operand ) " )
268
+ _ = visitForwardedUses ( introducer: value, context) { useResult in
269
+ print ( " USE: \( useResult ) " )
255
270
return . continueWalk
256
271
}
257
272
}
0 commit comments