1- //===--- SimplifyBeginBorrow .swift ------- ---------------------------------===//
1+ //===--- SimplifyBeginAndLoadBorrow .swift ---------------------------------===//
22//
33// This source file is part of the Swift.org open source project
44//
1212
1313import SIL
1414
15- extension BeginBorrowInst : OnoneSimplifyable {
15+ extension BeginBorrowInst : OnoneSimplifyable , SILCombineSimplifyable {
1616 func simplify( _ context: SimplifyContext ) {
1717 if borrowedValue. ownership == . owned,
1818 // We need to keep lexical lifetimes in place.
@@ -21,10 +21,51 @@ extension BeginBorrowInst : OnoneSimplifyable {
2121 !findPointerEscapingUse( of: borrowedValue)
2222 {
2323 tryReplaceBorrowWithOwnedOperand ( beginBorrow: self , context)
24+ } else {
25+ removeBorrowOfThinFunction ( beginBorrow: self , context)
2426 }
2527 }
2628}
2729
30+ extension LoadBorrowInst : Simplifyable , SILCombineSimplifyable {
31+ func simplify( _ context: SimplifyContext ) {
32+ if uses. ignoreDebugUses. ignoreUsers ( ofType: EndBorrowInst . self) . isEmpty {
33+ context. erase ( instructionIncludingAllUsers: self )
34+ return
35+ }
36+
37+ // If the load_borrow is followed by a copy_value, combine both into a `load [copy]`:
38+ // ```
39+ // %1 = load_borrow %0
40+ // %2 = some_forwarding_instruction %1 // zero or more forwarding instructions
41+ // %3 = copy_value %2
42+ // end_borrow %1
43+ // ```
44+ // ->
45+ // ```
46+ // %1 = load [copy] %0
47+ // %3 = some_forwarding_instruction %1 // zero or more forwarding instructions
48+ // ```
49+ //
50+ tryCombineWithCopy ( context)
51+ }
52+
53+ private func tryCombineWithCopy( _ context: SimplifyContext ) {
54+ let forwardedValue = lookThroughSingleForwardingUses ( )
55+ guard let singleUser = forwardedValue. uses. ignoreUsers ( ofType: EndBorrowInst . self) . singleUse? . instruction,
56+ let copy = singleUser as? CopyValueInst ,
57+ copy. parentBlock == self . parentBlock else {
58+ return
59+ }
60+ let builder = Builder ( before: self , context)
61+ let loadCopy = builder. createLoad ( fromAddress: address, ownership: . copy)
62+ let forwardedOwnedValue = replace ( guaranteedValue: self , withOwnedValue: loadCopy, context)
63+ copy. uses. replaceAll ( with: forwardedOwnedValue, context)
64+ context. erase ( instruction: copy)
65+ context. erase ( instructionIncludingAllUsers: self )
66+ }
67+ }
68+
2869private func tryReplaceBorrowWithOwnedOperand( beginBorrow: BeginBorrowInst , _ context: SimplifyContext ) {
2970 // The last value of a (potentially empty) forwarding chain, beginning at the `begin_borrow`.
3071 let forwardedValue = beginBorrow. lookThroughSingleForwardingUses ( )
@@ -38,6 +79,19 @@ private func tryReplaceBorrowWithOwnedOperand(beginBorrow: BeginBorrowInst, _ co
3879 }
3980}
4081
82+ private func removeBorrowOfThinFunction( beginBorrow: BeginBorrowInst , _ context: SimplifyContext ) {
83+ guard let thin2thickFn = beginBorrow. borrowedValue as? ThinToThickFunctionInst ,
84+ // For simplicity don't go into the trouble of removing reborrow phi arguments.
85+ beginBorrow. uses. filterUsers ( ofType: BranchInst . self) . isEmpty else
86+ {
87+ return
88+ }
89+ // `thin_to_thick_function` has "none" ownership and is compatible with guaranteed values.
90+ // Therefore the `begin_borrow` is not needed.
91+ beginBorrow. uses. ignoreUsers ( ofType: EndBorrowInst . self) . replaceAll ( with: thin2thickFn, context)
92+ context. erase ( instructionIncludingAllUsers: beginBorrow)
93+ }
94+
4195/// Replace
4296/// ```
4397/// %1 = begin_borrow %0
@@ -156,7 +210,7 @@ private extension ForwardingInstruction {
156210}
157211
158212/// Replaces a guaranteed value with an owned value.
159- ///
213+ ///
160214/// If the `guaranteedValue`'s use is a ForwardingInstruction (or forwarding instruction chain),
161215/// it is converted to an owned version of the forwarding instruction (or instruction chain).
162216///
0 commit comments