@@ -76,20 +76,34 @@ class ShrinkBorrowScope {
76
76
// The instructions from which the shrinking starts, the scope ending
77
77
// instructions, keyed off the block in which they appear.
78
78
llvm::SmallDenseMap<SILBasicBlock *, SILInstruction *> startingInstructions;
79
+ // The end _borrow instructions for this borrow scope that existed before
80
+ // ShrinkBorrowScope ran and which were not modified.
81
+ llvm::SmallPtrSet<SILInstruction *, 8 > reusedEndBorrowInsts;
82
+
83
+ // Whether ShrinkBorrowScope made any changes to the function.
84
+ //
85
+ // It could have made one of the following sorts of changes:
86
+ // - deleted an end_borrow
87
+ // - created an end_borrow
88
+ // - rewrote the operand of an instruction
89
+ // - ApplySite
90
+ // - begin_borrow
91
+ // - copy_value
92
+ bool madeChange;
79
93
80
94
public:
81
95
ShrinkBorrowScope (BeginBorrowInst *bbi, InstructionDeleter &deleter,
82
96
SmallVectorImpl<CopyValueInst *> &modifiedCopyValueInsts)
83
97
: introducer(bbi), deleter(deleter),
84
- modifiedCopyValueInsts (modifiedCopyValueInsts) {}
98
+ modifiedCopyValueInsts (modifiedCopyValueInsts), madeChange( false ) {}
85
99
86
100
bool run ();
87
101
88
102
bool populateUsers ();
89
103
bool initializeWorklist ();
90
104
void findBarriers ();
91
- void rewrite ();
92
- void createEndBorrow (SILInstruction *insertionPoint);
105
+ bool rewrite ();
106
+ bool createEndBorrow (SILInstruction *insertionPoint);
93
107
94
108
bool isBarrierApply (SILInstruction *instruction) {
95
109
// For now, treat every apply (that doesn't use the borrowed value) as a
@@ -165,8 +179,10 @@ class ShrinkBorrowScope {
165
179
if (auto *cvi = dyn_cast<CopyValueInst>(argument)) {
166
180
cvi->setOperand (borrowee);
167
181
modifiedCopyValueInsts.push_back (cvi);
182
+ madeChange = true ;
168
183
} else {
169
184
apply.setArgument (index, borrowee);
185
+ madeChange = true ;
170
186
}
171
187
}
172
188
return true ;
@@ -175,12 +191,14 @@ class ShrinkBorrowScope {
175
191
canReplaceValueWithBorrowedValue (bbi->getOperand ())) {
176
192
auto borrowee = introducer->getOperand ();
177
193
bbi->setOperand (borrowee);
194
+ madeChange = true ;
178
195
return true ;
179
196
}
180
197
} else if (auto *cvi = dyn_cast<CopyValueInst>(instruction)) {
181
198
if (canReplaceValueWithBorrowedValue (cvi->getOperand ())) {
182
199
auto borrowee = introducer->getOperand ();
183
200
cvi->setOperand (borrowee);
201
+ madeChange = true ;
184
202
modifiedCopyValueInsts.push_back (cvi);
185
203
return true ;
186
204
}
@@ -205,9 +223,9 @@ bool ShrinkBorrowScope::run() {
205
223
206
224
findBarriers ();
207
225
208
- rewrite ();
226
+ madeChange |= rewrite ();
209
227
210
- return true ;
228
+ return madeChange ;
211
229
}
212
230
213
231
bool ShrinkBorrowScope::populateUsers () {
@@ -311,31 +329,50 @@ void ShrinkBorrowScope::findBarriers() {
311
329
}
312
330
}
313
331
314
- void ShrinkBorrowScope::rewrite () {
315
- // Remove all the original end_borrow instructions.
316
- for (auto pair : startingInstructions) {
317
- deleter.forceDelete (pair.getSecond ());
318
- }
332
+ bool ShrinkBorrowScope::rewrite () {
333
+ bool createdBorrow = false ;
319
334
320
335
// Insert the new end_borrow instructions that occur after deinit barriers.
321
336
for (auto pair : barrierInstructions) {
322
337
auto *insertionPoint = getNextInstruction (pair.second );
323
- createEndBorrow (insertionPoint);
338
+ createdBorrow |= createEndBorrow (insertionPoint);
324
339
}
325
340
326
341
// Insert the new end_borrow instructions that occur at the beginning of
327
342
// blocks which we couldn't hoist out of.
328
343
for (auto *block : barredBlocks) {
329
344
auto *insertionPoint = &*block->begin ();
330
- createEndBorrow (insertionPoint);
345
+ createdBorrow |= createEndBorrow (insertionPoint);
346
+ }
347
+
348
+ if (createdBorrow) {
349
+ // Remove all the original end_borrow instructions.
350
+ for (auto pair : startingInstructions) {
351
+ if (reusedEndBorrowInsts.contains (pair.second )) {
352
+ continue ;
353
+ }
354
+ deleter.forceDelete (pair.getSecond ());
355
+ }
331
356
}
357
+
358
+ return createdBorrow;
332
359
}
333
360
334
- void ShrinkBorrowScope::createEndBorrow (SILInstruction *insertionPoint) {
361
+ bool ShrinkBorrowScope::createEndBorrow (SILInstruction *insertionPoint) {
362
+ if (auto *ebi = dyn_cast<EndBorrowInst>(insertionPoint)) {
363
+ llvm::SmallDenseMap<SILBasicBlock *, SILInstruction *>::iterator location;
364
+ if ((location = llvm::find_if (startingInstructions, [&](auto pair) -> bool {
365
+ return pair.second == insertionPoint;
366
+ })) != startingInstructions.end ()) {
367
+ reusedEndBorrowInsts.insert (location->second );
368
+ return false ;
369
+ }
370
+ }
335
371
auto builder = SILBuilderWithScope (insertionPoint);
336
372
builder.createEndBorrow (
337
373
RegularLocation::getAutoGeneratedLocation (insertionPoint->getLoc ()),
338
374
introducer);
375
+ return true ;
339
376
}
340
377
341
378
bool swift::shrinkBorrowScope (
0 commit comments