@@ -122,7 +122,11 @@ private struct Uses {
122122 // Exit blocks of the load/copy_value's liverange which don't have a destroy.
123123 // Those are successor blocks of terminators, like `switch_enum`, which do _not_ forward the value.
124124 // 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+ }
126130
127131 private( set) var usersInDeadEndBlocks : Stack < Instruction >
128132
@@ -179,7 +183,7 @@ private struct Uses {
179183 // A terminator instruction can implicitly end the lifetime of its operand in a success block,
180184 // e.g. a `switch_enum` with a non-payload case block. Such success blocks need an `end_borrow`, though.
181185 for succ in termInst. successors where !succ. arguments. contains ( where: { $0. ownership == . owned} ) {
182- nonDestroyingLiverangeExits. append ( succ)
186+ nonDestroyingLiverangeExits. append ( succ. instructions . first! )
183187 }
184188 }
185189 }
@@ -268,7 +272,7 @@ private func remove(copy: CopyValueInst, collectedUses: Uses, liverange: Instruc
268272 context. erase ( instructions: collectedUses. destroys)
269273}
270274
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`.
272276// In this case we have to preserve the move's flags by inserting a `begin_borrow` with the same flags.
273277// For example:
274278//
@@ -314,15 +318,11 @@ private func createEndBorrows(for beginBorrow: Value, atEndOf liverange: Instruc
314318 // destroy_value %2
315319 // destroy_value %3 // The final destroy. Here we need to create the `end_borrow`(s)
316320 //
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+ }
326326 }
327327}
328328
0 commit comments