1313import SIL
1414import OptimizerBridging
1515
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+
1628/// Update all borrowed-from instructions in the `function`
1729func updateBorrowedFrom( in function: Function , _ context: some MutatingContext ) {
1830 if !function. hasOwnership {
@@ -54,6 +66,47 @@ func updateBorrowedFrom(for phis: some Sequence<Phi>, _ context: some MutatingCo
5466 } while changed
5567}
5668
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+
57110private func updateBorrowedFrom( for phi: Phi , _ context: some MutatingContext ) -> Bool {
58111 var computedEVs = Stack < Value > ( context)
59112 defer { computedEVs. deinitialize ( ) }
@@ -103,7 +156,7 @@ func registerBorrowArgumentsUpdater() {
103156 { ( bridgedCtxt: BridgedPassContext , bridgedFunction: BridgedFunction ) in
104157 let context = FunctionPassContext ( _bridged: bridgedCtxt)
105158 let function = bridgedFunction. function;
106- updateBorrowedFrom ( in: function, context)
159+ updateBorrowArguments ( in: function, context)
107160 } ,
108161 { ( bridgedCtxt: BridgedPassContext , bridgedPhiArray: BridgedArrayRef ) in
109162 let context = FunctionPassContext ( _bridged: bridgedCtxt)
@@ -117,7 +170,7 @@ func registerBorrowArgumentsUpdater() {
117170 }
118171 }
119172 }
120- updateBorrowedFrom ( for: guaranteedPhis, context)
173+ updateBorrowArguments ( for: guaranteedPhis, context)
121174 }
122175 )
123176}
0 commit comments