1
- //===--- SimplifyBeginBorrow .swift ------- ---------------------------------===//
1
+ //===--- SimplifyBeginAndLoadBorrow .swift ---------------------------------===//
2
2
//
3
3
// This source file is part of the Swift.org open source project
4
4
//
12
12
13
13
import SIL
14
14
15
- extension BeginBorrowInst : OnoneSimplifyable {
15
+ extension BeginBorrowInst : OnoneSimplifyable , SILCombineSimplifyable {
16
16
func simplify( _ context: SimplifyContext ) {
17
17
if borrowedValue. ownership == . owned,
18
18
// We need to keep lexical lifetimes in place.
@@ -21,10 +21,51 @@ extension BeginBorrowInst : OnoneSimplifyable {
21
21
!findPointerEscapingUse( of: borrowedValue)
22
22
{
23
23
tryReplaceBorrowWithOwnedOperand ( beginBorrow: self , context)
24
+ } else {
25
+ removeBorrowOfThinFunction ( beginBorrow: self , context)
24
26
}
25
27
}
26
28
}
27
29
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
+
28
69
private func tryReplaceBorrowWithOwnedOperand( beginBorrow: BeginBorrowInst , _ context: SimplifyContext ) {
29
70
// The last value of a (potentially empty) forwarding chain, beginning at the `begin_borrow`.
30
71
let forwardedValue = beginBorrow. lookThroughSingleForwardingUses ( )
@@ -38,6 +79,19 @@ private func tryReplaceBorrowWithOwnedOperand(beginBorrow: BeginBorrowInst, _ co
38
79
}
39
80
}
40
81
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
+
41
95
/// Replace
42
96
/// ```
43
97
/// %1 = begin_borrow %0
@@ -156,7 +210,7 @@ private extension ForwardingInstruction {
156
210
}
157
211
158
212
/// Replaces a guaranteed value with an owned value.
159
- ///
213
+ ///
160
214
/// If the `guaranteedValue`'s use is a ForwardingInstruction (or forwarding instruction chain),
161
215
/// it is converted to an owned version of the forwarding instruction (or instruction chain).
162
216
///
0 commit comments