@@ -122,7 +122,11 @@ private struct Uses {
122
122
// Exit blocks of the load/copy_value's liverange which don't have a destroy.
123
123
// Those are successor blocks of terminators, like `switch_enum`, which do _not_ forward the value.
124
124
// E.g. the none-case of a switch_enum of an Optional.
125
- private( set) var nonDestroyingLiverangeExits : Stack < BasicBlock >
125
+ private( set) var nonDestroyingLiverangeExits : Stack < Instruction >
126
+
127
+ var allLifetimeEndingInstructions : [ Instruction ] {
128
+ Array ( destroys. lazy. map { $0 } ) + Array( nonDestroyingLiverangeExits)
129
+ }
126
130
127
131
private( set) var usersInDeadEndBlocks : Stack < Instruction >
128
132
@@ -179,7 +183,7 @@ private struct Uses {
179
183
// A terminator instruction can implicitly end the lifetime of its operand in a success block,
180
184
// e.g. a `switch_enum` with a non-payload case block. Such success blocks need an `end_borrow`, though.
181
185
for succ in termInst. successors where !succ. arguments. contains ( where: { $0. ownership == . owned} ) {
182
- nonDestroyingLiverangeExits. append ( succ)
186
+ nonDestroyingLiverangeExits. append ( succ. instructions . first! )
183
187
}
184
188
}
185
189
}
@@ -268,7 +272,7 @@ private func remove(copy: CopyValueInst, collectedUses: Uses, liverange: Instruc
268
272
context. erase ( instructions: collectedUses. destroys)
269
273
}
270
274
271
- // Handle the special case if the `load` or `copy_valuw ` is immediately followed by a single `move_value`.
275
+ // Handle the special case if the `load` or `copy_value ` is immediately followed by a single `move_value`.
272
276
// In this case we have to preserve the move's flags by inserting a `begin_borrow` with the same flags.
273
277
// For example:
274
278
//
@@ -314,15 +318,11 @@ private func createEndBorrows(for beginBorrow: Value, atEndOf liverange: Instruc
314
318
// destroy_value %2
315
319
// destroy_value %3 // The final destroy. Here we need to create the `end_borrow`(s)
316
320
//
317
- for destroy in collectedUses. destroys where !liverange. contains ( destroy) {
318
- let builder = Builder ( before: destroy, context)
319
- builder. createEndBorrow ( of: beginBorrow)
320
- }
321
- for liverangeExitBlock in collectedUses. nonDestroyingLiverangeExits where
322
- !liverange. blockRange. contains ( liverangeExitBlock)
323
- {
324
- let builder = Builder ( atBeginOf: liverangeExitBlock, context)
325
- builder. createEndBorrow ( of: beginBorrow)
321
+ for endInst in collectedUses. allLifetimeEndingInstructions {
322
+ if !liverange. contains ( endInst) {
323
+ let builder = Builder ( before: endInst, context)
324
+ builder. createEndBorrow ( of: beginBorrow)
325
+ }
326
326
}
327
327
}
328
328
0 commit comments