13
13
import SIL
14
14
import OptimizerBridging
15
15
16
+ /// Updates the reborrow flags and the borrowed-from instructions for all guaranteed phis in `function`.
17
+ func updateBorrowArguments( in function: Function , _ context: some MutatingContext ) {
18
+ updateReborrowFlags ( in: function, context)
19
+ updateBorrowedFrom ( in: function, context)
20
+ }
21
+
22
+ /// Updates the reborrow flags and the borrowed-from instructions for all `phis`.
23
+ func updateBorrowArguments( for phis: some Sequence < Phi > , _ context: some MutatingContext ) {
24
+ updateReborrowFlags ( for: phis, context)
25
+ updateBorrowedFrom ( for: phis, context)
26
+ }
27
+
16
28
/// Update all borrowed-from instructions in the `function`
17
29
func updateBorrowedFrom( in function: Function , _ context: some MutatingContext ) {
18
30
if !function. hasOwnership {
@@ -54,6 +66,47 @@ func updateBorrowedFrom(for phis: some Sequence<Phi>, _ context: some MutatingCo
54
66
} while changed
55
67
}
56
68
69
+ /// Updates the reborrow flags for all guaranteed phis in `function`.
70
+ func updateReborrowFlags( in function: Function , _ context: some MutatingContext ) {
71
+ if !function. hasOwnership {
72
+ return
73
+ }
74
+ var guaranteedPhis = Stack < Phi > ( context)
75
+ defer { guaranteedPhis. deinitialize ( ) }
76
+
77
+ for block in function. blocks. reversed ( ) {
78
+ for arg in block. arguments {
79
+ if let phi = Phi ( arg) , phi. value. ownership == . guaranteed {
80
+ guaranteedPhis. append ( phi)
81
+ }
82
+ }
83
+ }
84
+ updateReborrowFlags ( for: guaranteedPhis, context)
85
+ }
86
+
87
+ /// Updates the reborrow flags for all `phis`.
88
+ func updateReborrowFlags( for phis: some Sequence < Phi > , _ context: some MutatingContext ) {
89
+ // TODO: clear reborrow flags before re-computing when we have complete OSSA lifetimes.
90
+ // It would be cleaner to first clear all flags. But this is not possible because some end_borrow instructions
91
+ // might be missing in dead-end blocks. This will be fixed with complete OSSA lifetimes.
92
+
93
+ if let phi = phis. first ( where: { phi in true } ) , !phi. value. parentFunction. hasOwnership {
94
+ return
95
+ }
96
+
97
+ var changed : Bool
98
+ repeat {
99
+ changed = false
100
+
101
+ for phi in phis where phi. value. ownership == . guaranteed {
102
+ if !phi. value. isReborrow && phi. hasBorrowEndingUse {
103
+ phi. value. set ( reborrow: true , context)
104
+ changed = true
105
+ }
106
+ }
107
+ } while changed
108
+ }
109
+
57
110
private func updateBorrowedFrom( for phi: Phi , _ context: some MutatingContext ) -> Bool {
58
111
var computedEVs = Stack < Value > ( context)
59
112
defer { computedEVs. deinitialize ( ) }
@@ -103,7 +156,7 @@ func registerBorrowArgumentsUpdater() {
103
156
{ ( bridgedCtxt: BridgedPassContext , bridgedFunction: BridgedFunction ) in
104
157
let context = FunctionPassContext ( _bridged: bridgedCtxt)
105
158
let function = bridgedFunction. function;
106
- updateBorrowedFrom ( in: function, context)
159
+ updateBorrowArguments ( in: function, context)
107
160
} ,
108
161
{ ( bridgedCtxt: BridgedPassContext , bridgedPhiArray: BridgedArrayRef ) in
109
162
let context = FunctionPassContext ( _bridged: bridgedCtxt)
@@ -117,7 +170,7 @@ func registerBorrowArgumentsUpdater() {
117
170
}
118
171
}
119
172
}
120
- updateBorrowedFrom ( for: guaranteedPhis, context)
173
+ updateBorrowArguments ( for: guaranteedPhis, context)
121
174
}
122
175
)
123
176
}
0 commit comments