@@ -102,6 +102,14 @@ void LinearLiveness::compute() {
102
102
LinearLivenessVisitor (*this ).visitLifetimeEndingUses (ownershipDef);
103
103
}
104
104
105
+ // / Override OwnershipUseVisitor to callback to handleInnerScopeCallback for
106
+ // / nested borrow scopes. This supports lifetime completion from the inside-out.
107
+ // /
108
+ // / By default, handleOwnedPhi and handleOuterReborrow are already treated like
109
+ // / a normal lifetime-ending use.
110
+ // /
111
+ // / By default, handleGuaranteedForwardingPhi is already treated like a normal
112
+ // / non-lifetime-ending use.
105
113
struct InteriorLivenessVisitor :
106
114
public OwnershipUseVisitor<InteriorLivenessVisitor> {
107
115
@@ -142,14 +150,7 @@ struct InteriorLivenessVisitor :
142
150
143
151
bool handlePointerEscape (Operand *use) {
144
152
interiorLiveness.addressUseKind = AddressUseKind::PointerEscape;
145
- return true ;
146
- }
147
153
148
- // handleOwnedPhi and handleOuterReborrow ends the linear lifetime.
149
- // By default, they are treated like a normal lifetime-ending use.
150
-
151
- bool handleGuaranteedForwardingPhi (Operand *use) {
152
- recursivelyVisitInnerGuaranteedPhi (PhiOperand (use), /* reborrow*/ false );
153
154
return true ;
154
155
}
155
156
@@ -166,18 +167,6 @@ struct InteriorLivenessVisitor :
166
167
return true ;
167
168
}
168
169
169
- bool handleInnerAdjacentReborrow (SILArgument *reborrow) {
170
- if (handleInnerScopeCallback) {
171
- handleInnerScopeCallback (reborrow);
172
- }
173
- return true ;
174
- }
175
-
176
- bool handleInnerReborrow (Operand *phiOper) {
177
- recursivelyVisitInnerGuaranteedPhi (PhiOperand (phiOper), /* reborrow*/ true );
178
- return true ;
179
- }
180
-
181
170
// / After this returns true, handleUsePoint will be called on the scope
182
171
// / ending operands.
183
172
// /
@@ -188,88 +177,8 @@ struct InteriorLivenessVisitor :
188
177
}
189
178
return true ;
190
179
}
191
-
192
- void recursivelyVisitInnerGuaranteedPhi (PhiOperand phiOper, bool isReborrow);
193
180
};
194
181
195
- // Dominating ownershipDef example: handleReborrow must continue visiting phi
196
- // uses:
197
- //
198
- // bb0:
199
- // d1 = ...
200
- // cond_br bb1, bb2
201
- // bb1:
202
- // b1 = borrow d1
203
- // br bb3(b1)
204
- // bb2:
205
- // b2 = borrow d1
206
- // br bb3(b2)
207
- // bb3(reborrow):
208
- // u1 = d1
209
- // u2 = reborrow
210
- // // can't move destroy above u2
211
- // destroy_value d1
212
- //
213
- // Dominating ownershipDef example: handleGuaranteedForwardingPhi must continue
214
- // visiting phi uses:
215
- //
216
- // bb0:
217
- // b1 = borrow d1
218
- // cond_br bb1, bb2
219
- // bb1:
220
- // p1 = projection b1
221
- // br bb3(p1)
222
- // bb2:
223
- // p1 = projection b1
224
- // br bb3(p2)
225
- // bb3(forwardingPhi):
226
- // u1 = b1
227
- // u2 = forwardingPhi
228
- // // can't move end_borrow above u2
229
- // end_borrow b1
230
- //
231
- // TODO: when phi's have a reborrow flag, remove \p isReborrow.
232
- void InteriorLivenessVisitor::
233
- recursivelyVisitInnerGuaranteedPhi (PhiOperand phiOper, bool isReborrow) {
234
- SILValue phiValue = phiOper.getValue ();
235
- if (!visited.insert (phiValue))
236
- return ;
237
-
238
- if (!visitEnclosingDefs (phiValue, [this ](SILValue enclosingDef){
239
- // If the enclosing def is \p ownershipDef, return false to check
240
- // dominance.
241
- if (enclosingDef == interiorLiveness.ownershipDef )
242
- return false ;
243
-
244
- // Otherwise, phiValue is enclosed by an outer adjacent phi, so its scope
245
- // does not contribute to the outer liveness. This phi will be recorded as a
246
- // regular use by the visitor, and this enclosing def will be visited as
247
- // separate lifetime-ending-use use. Return true to continue checking if any
248
- // other enclosing defs do not have an outer adjacent reborrow.
249
- return true ;
250
- })) {
251
- // TODO: instead of relying on Dominance, we can reformulate this algorithm
252
- // to detect redundant phis, similar to the SSAUpdater.
253
- //
254
- // At least one enclosing def is ownershipDef. If ownershipDef dominates
255
- // phiValue, then this is consistent with a well-formed linear lifetime, and
256
- // the phi's uses directly contribute to ownershipDef's liveness.
257
- if (domInfo &&
258
- domInfo->dominates (interiorLiveness.ownershipDef ->getParentBlock (),
259
- phiValue->getParentBlock ())) {
260
- if (isReborrow) {
261
- visitInnerBorrow (phiOper.getOperand ());
262
- } else {
263
- visitInteriorUses (phiValue);
264
- }
265
- return ;
266
- }
267
- // ownershipDef does not dominate this phi. Record it so the liveness
268
- // client can use this information to insert the missing outer adjacent phi.
269
- interiorLiveness.unenclosedPhis .push_back (phiValue);
270
- }
271
- }
272
-
273
182
void InteriorLiveness::compute (const DominanceInfo *domInfo, InnerScopeHandlerRef handleInnerScope) {
274
183
liveness.initializeDef (ownershipDef);
275
184
addressUseKind = AddressUseKind::NonEscaping;
@@ -291,11 +200,6 @@ void InteriorLiveness::print(llvm::raw_ostream &OS) const {
291
200
OS << " Incomplete liveness: Unknown address use\n " ;
292
201
break ;
293
202
}
294
- OS << " Unenclosed phis {\n " ;
295
- for (SILValue phi : getUnenclosedPhis ()) {
296
- OS << " " << phi;
297
- }
298
- OS << " }\n " ;
299
203
}
300
204
301
205
void InteriorLiveness::dump () const { print (llvm::dbgs ()); }
0 commit comments