@@ -51,79 +51,9 @@ void PrunedLiveBlocks::computeUseBlockLiveness(SILBasicBlock *userBB) {
5151}
5252
5353// ===----------------------------------------------------------------------===//
54- // MARK: PrunedLiveness
54+ // PrunedLiveBlocks and PrunedLiveness
5555// ===----------------------------------------------------------------------===//
5656
57- void PrunedLiveness::updateForUse (SILInstruction *user, bool lifetimeEnding) {
58- liveBlocks.updateForUse (user);
59-
60- // Note that a user may use the current value from multiple operands. If any
61- // of the uses are non-lifetime-ending, then we must consider the user
62- // itself non-lifetime-ending; it cannot be a final destroy point because
63- // the value of the non-lifetime-ending operand must be kept alive until the
64- // end of the user. Consider a call that takes the same value using
65- // different conventions:
66- //
67- // apply %f(%val, %val) : $(@guaranteed, @owned) -> ()
68- //
69- // This call is not considered the end of %val's lifetime. The @owned
70- // argument must be copied.
71- auto iterAndSuccess = users.insert ({user, lifetimeEnding});
72- if (!iterAndSuccess.second )
73- iterAndSuccess.first ->second &= lifetimeEnding;
74- }
75-
76- InnerBorrowKind PrunedLiveness::updateForBorrowingOperand (Operand *operand) {
77- assert (operand->getOperandOwnership () == OperandOwnership::Borrow);
78-
79- // A nested borrow scope is considered a use-point at each scope ending
80- // instruction.
81- //
82- // Note: Ownership liveness should follow reborrows that are dominated by the
83- // ownership definition.
84- if (!BorrowingOperand (operand).visitScopeEndingUses ([this ](Operand *end) {
85- if (end->getOperandOwnership () == OperandOwnership::Reborrow) {
86- return false ;
87- }
88- updateForUse (end->getUser (), /* lifetimeEnding*/ false );
89- return true ;
90- })) {
91- return InnerBorrowKind::Reborrowed;
92- }
93- return InnerBorrowKind::Contained;
94- }
95-
96- AddressUseKind PrunedLiveness::checkAndUpdateInteriorPointer (Operand *operand) {
97- assert (operand->getOperandOwnership () == OperandOwnership::InteriorPointer);
98-
99- if (auto scopedAddress = ScopedAddressValue::forUse (operand)) {
100- scopedAddress.visitScopeEndingUses ([this ](Operand *end) {
101- updateForUse (end->getUser (), /* lifetimeEnding*/ false );
102- return true ;
103- });
104- return AddressUseKind::NonEscaping;
105- }
106- // FIXME: findTransitiveUses should be a visitor so we're not recursively
107- // allocating use vectors and potentially merging the use points.
108- SmallVector<Operand *, 8 > uses;
109- auto useKind = InteriorPointerOperand (operand).findTransitiveUses (&uses);
110- for (auto *use : uses) {
111- updateForUse (use->getUser (), /* lifetimeEnding*/ false );
112- }
113- if (uses.empty ()) {
114- // Handle a dead address
115- updateForUse (operand->getUser (), /* lifetimeEnding*/ false );
116- }
117- return useKind;
118- }
119-
120- void PrunedLiveness::extendAcrossLiveness (PrunedLiveness &otherLivesness) {
121- // update this liveness for all the interesting users in otherLiveness.
122- for (std::pair<SILInstruction *, bool > userAndEnd : otherLivesness.users ) {
123- updateForUse (userAndEnd.first , userAndEnd.second );
124- }
125- }
126-
12757llvm::StringRef PrunedLiveBlocks::getStringRef (IsLive isLive) const {
12858 switch (isLive) {
12959 case Dead:
@@ -235,6 +165,85 @@ void PrunedLivenessBoundary::visitInsertionPoints(
235165// PrunedLiveRange
236166// ===----------------------------------------------------------------------===//
237167
168+ template <typename LivenessWithDefs>
169+ void PrunedLiveRange<LivenessWithDefs>::updateForUse(SILInstruction *user,
170+ bool lifetimeEnding) {
171+ liveBlocks.updateForUse (user);
172+
173+ // Note that a user may use the current value from multiple operands. If any
174+ // of the uses are non-lifetime-ending, then we must consider the user
175+ // itself non-lifetime-ending; it cannot be a final destroy point because
176+ // the value of the non-lifetime-ending operand must be kept alive until the
177+ // end of the user. Consider a call that takes the same value using
178+ // different conventions:
179+ //
180+ // apply %f(%val, %val) : $(@guaranteed, @owned) -> ()
181+ //
182+ // This call is not considered the end of %val's lifetime. The @owned
183+ // argument must be copied.
184+ auto iterAndSuccess = users.insert ({user, lifetimeEnding});
185+ if (!iterAndSuccess.second )
186+ iterAndSuccess.first ->second &= lifetimeEnding;
187+ }
188+
189+ template <typename LivenessWithDefs>
190+ InnerBorrowKind
191+ PrunedLiveRange<LivenessWithDefs>::updateForBorrowingOperand(Operand *operand) {
192+ assert (operand->getOperandOwnership () == OperandOwnership::Borrow);
193+
194+ // A nested borrow scope is considered a use-point at each scope ending
195+ // instruction.
196+ //
197+ // Note: Ownership liveness should follow reborrows that are dominated by the
198+ // ownership definition.
199+ if (!BorrowingOperand (operand).visitScopeEndingUses ([this ](Operand *end) {
200+ if (end->getOperandOwnership () == OperandOwnership::Reborrow) {
201+ return false ;
202+ }
203+ updateForUse (end->getUser (), /* lifetimeEnding*/ false );
204+ return true ;
205+ })) {
206+ return InnerBorrowKind::Reborrowed;
207+ }
208+ return InnerBorrowKind::Contained;
209+ }
210+
211+ template <typename LivenessWithDefs>
212+ AddressUseKind PrunedLiveRange<LivenessWithDefs>::checkAndUpdateInteriorPointer(
213+ Operand *operand) {
214+ assert (operand->getOperandOwnership () == OperandOwnership::InteriorPointer);
215+
216+ if (auto scopedAddress = ScopedAddressValue::forUse (operand)) {
217+ scopedAddress.visitScopeEndingUses ([this ](Operand *end) {
218+ updateForUse (end->getUser (), /* lifetimeEnding*/ false );
219+ return true ;
220+ });
221+ return AddressUseKind::NonEscaping;
222+ }
223+ // FIXME: findTransitiveUses should be a visitor so we're not recursively
224+ // allocating use vectors and potentially merging the use points.
225+ SmallVector<Operand *, 8 > uses;
226+ auto useKind = InteriorPointerOperand (operand).findTransitiveUses (&uses);
227+ for (auto *use : uses) {
228+ updateForUse (use->getUser (), /* lifetimeEnding*/ false );
229+ }
230+ if (uses.empty ()) {
231+ // Handle a dead address
232+ updateForUse (operand->getUser (), /* lifetimeEnding*/ false );
233+ }
234+ return useKind;
235+ }
236+
237+ template <typename LivenessWithDefs>
238+ void PrunedLiveRange<LivenessWithDefs>::extendAcrossLiveness(
239+ PrunedLiveness &otherLiveness) {
240+ // update this liveness for all the interesting users in otherLiveness.
241+ for (std::pair<SILInstruction *, bool > userAndEnd :
242+ otherLiveness.getAllUsers ()) {
243+ updateForUse (userAndEnd.first , userAndEnd.second );
244+ }
245+ }
246+
238247template <typename LivenessWithDefs>
239248LiveRangeSummary PrunedLiveRange<LivenessWithDefs>::updateForDef(SILValue def) {
240249 ValueSet visited (def->getFunction ());
@@ -606,7 +615,7 @@ LiveRangeSummary MultiDefPrunedLiveness::computeSimple() {
606615// liveness, clients should check uses that are in PrunedLivenessBoundary.
607616void DiagnosticPrunedLiveness::
608617updateForUse (SILInstruction *user, bool lifetimeEnding) {
609- PrunedLiveness ::updateForUse (user, 0 );
618+ SSAPrunedLiveness ::updateForUse (user, 0 );
610619
611620 auto useBlockLive = getBlockLiveness (user->getParent ());
612621 // Record all uses of blocks on the liveness boundary. For blocks marked
0 commit comments