@@ -51,79 +51,9 @@ void PrunedLiveBlocks::computeUseBlockLiveness(SILBasicBlock *userBB) {
51
51
}
52
52
53
53
// ===----------------------------------------------------------------------===//
54
- // MARK: PrunedLiveness
54
+ // PrunedLiveBlocks and PrunedLiveness
55
55
// ===----------------------------------------------------------------------===//
56
56
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
-
127
57
llvm::StringRef PrunedLiveBlocks::getStringRef (IsLive isLive) const {
128
58
switch (isLive) {
129
59
case Dead:
@@ -235,6 +165,85 @@ void PrunedLivenessBoundary::visitInsertionPoints(
235
165
// PrunedLiveRange
236
166
// ===----------------------------------------------------------------------===//
237
167
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
+
238
247
template <typename LivenessWithDefs>
239
248
LiveRangeSummary PrunedLiveRange<LivenessWithDefs>::updateForDef(SILValue def) {
240
249
ValueSet visited (def->getFunction ());
@@ -606,7 +615,7 @@ LiveRangeSummary MultiDefPrunedLiveness::computeSimple() {
606
615
// liveness, clients should check uses that are in PrunedLivenessBoundary.
607
616
void DiagnosticPrunedLiveness::
608
617
updateForUse (SILInstruction *user, bool lifetimeEnding) {
609
- PrunedLiveness ::updateForUse (user, 0 );
618
+ SSAPrunedLiveness ::updateForUse (user, 0 );
610
619
611
620
auto useBlockLive = getBlockLiveness (user->getParent ());
612
621
// Record all uses of blocks on the liveness boundary. For blocks marked
0 commit comments