@@ -46,6 +46,9 @@ STATISTIC(NumLoadCopyConvertedToLoadBorrow,
46
46
namespace {
47
47
48
48
class LiveRange {
49
+ // / The parent value that introduces the live range.
50
+ SILValue value;
51
+
49
52
// / A list of destroy_values of the live range.
50
53
SmallVector<Operand *, 2 > destroyingUses;
51
54
@@ -83,6 +86,32 @@ class LiveRange {
83
86
ArrayRef<Operand *> getNonConsumingForwardingUses () const {
84
87
return generalForwardingUses;
85
88
}
89
+
90
+ // / A consuming operation that:
91
+ // /
92
+ // / 1. If \p insertEndBorrows is true inserts end borrows at all
93
+ // / destroying insts locations.
94
+ // /
95
+ // / 2. Deletes all destroy_values.
96
+ // /
97
+ // / 3. RAUW value with newGuaranteedValue.
98
+ // /
99
+ // / 4. Convert all of the general forwarding instructions from
100
+ // / @owned -> @guaranteed. "Like Dominoes".
101
+ // /
102
+ // / 5. Leaves all of the unknown consuming users alone. It is up to
103
+ // / the caller to handle converting their ownership.
104
+ void convertToGuaranteedAndRAUW (SILValue newGuaranteedValue,
105
+ InstModCallbacks callbacks) &&;
106
+
107
+ // / Given a new guaranteed value, insert end_borrow for the newGuaranteedValue
108
+ // / at all of our destroy_values in prepration for converting from owned to
109
+ // / guaranteed.
110
+ // /
111
+ // / This is used when converting load [copy] -> load_borrow.
112
+ void insertEndBorrowsAtDestroys (SILValue newGuaranteedValue,
113
+ DeadEndBlocks &deadEndBlocks,
114
+ ValueLifetimeAnalysis::Frontier &scratch);
86
115
};
87
116
88
117
} // end anonymous namespace
@@ -101,7 +130,8 @@ LiveRange::DestroyingInstsRange LiveRange::getDestroyingInsts() const {
101
130
}
102
131
103
132
LiveRange::LiveRange (SILValue value)
104
- : destroyingUses(), generalForwardingUses(), unknownConsumingUses() {
133
+ : value(value), destroyingUses(), generalForwardingUses(),
134
+ unknownConsumingUses() {
105
135
assert (value.getOwnershipKind () == ValueOwnershipKind::Owned);
106
136
107
137
// We know that our silvalue produces an @owned value. Look through all of our
@@ -198,6 +228,108 @@ LiveRange::LiveRange(SILValue value)
198
228
}
199
229
}
200
230
231
+ void LiveRange::insertEndBorrowsAtDestroys (
232
+ SILValue newGuaranteedValue, DeadEndBlocks &deadEndBlocks,
233
+ ValueLifetimeAnalysis::Frontier &scratch) {
234
+ assert (scratch.empty () && " Expected scratch to be initially empty?!" );
235
+
236
+ // Since we are looking through forwarding uses that can accept guaranteed
237
+ // parameters, we can have multiple destroy_value along the same path. We need
238
+ // to find the post-dominating block set of these destroy value to ensure that
239
+ // we do not insert multiple end_borrow.
240
+ //
241
+ // TODO: Hoist this out?
242
+ auto *inst = value->getDefiningInstruction ();
243
+ assert (inst && " Should only call this with value's that are actually part of "
244
+ " an instruction" );
245
+
246
+ ValueLifetimeAnalysis analysis (inst, getDestroyingInsts ());
247
+ bool foundCriticalEdges = !analysis.computeFrontier (
248
+ scratch, ValueLifetimeAnalysis::DontModifyCFG, &deadEndBlocks);
249
+ (void )foundCriticalEdges;
250
+ assert (!foundCriticalEdges);
251
+ auto loc = RegularLocation::getAutoGeneratedLocation ();
252
+ while (!scratch.empty ()) {
253
+ auto *insertPoint = scratch.pop_back_val ();
254
+ SILBuilderWithScope builder (insertPoint);
255
+ builder.createEndBorrow (loc, newGuaranteedValue);
256
+ }
257
+ }
258
+
259
+ void LiveRange::convertToGuaranteedAndRAUW (SILValue newGuaranteedValue,
260
+ InstModCallbacks callbacks) && {
261
+ assert (isa<SingleValueInstruction>(value) &&
262
+ " Can only convert single value instruction live ranges to guaranteed" );
263
+ while (!destroyingUses.empty ()) {
264
+ auto *d = destroyingUses.pop_back_val ();
265
+ callbacks.deleteInst (d->getUser ());
266
+ ++NumEliminatedInsts;
267
+ }
268
+
269
+ callbacks.eraseAndRAUWSingleValueInst (cast<SingleValueInstruction>(value),
270
+ newGuaranteedValue);
271
+
272
+ // Then change all of our guaranteed forwarding insts to have guaranteed
273
+ // ownership kind instead of what ever they previously had (ignoring trivial
274
+ // results);
275
+ while (!generalForwardingUses.empty ()) {
276
+ auto *i = generalForwardingUses.pop_back_val ()->getUser ();
277
+
278
+ // If this is a term inst, just convert all of its incoming values that are
279
+ // owned to be guaranteed.
280
+ if (auto *ti = dyn_cast<TermInst>(i)) {
281
+ for (auto &succ : ti->getSuccessors ()) {
282
+ auto *succBlock = succ.getBB ();
283
+
284
+ // If we do not have any arguments, then continue.
285
+ if (succBlock->args_empty ())
286
+ continue ;
287
+
288
+ for (auto *succArg : succBlock->getSILPhiArguments ()) {
289
+ // If we have an any value, just continue.
290
+ if (succArg->getOwnershipKind () == ValueOwnershipKind::Owned) {
291
+ succArg->setOwnershipKind (ValueOwnershipKind::Guaranteed);
292
+ }
293
+ }
294
+ }
295
+ continue ;
296
+ }
297
+
298
+ assert (i->hasResults ());
299
+ for (SILValue result : i->getResults ()) {
300
+ if (auto *svi = dyn_cast<OwnershipForwardingSingleValueInst>(result)) {
301
+ if (svi->getOwnershipKind () == ValueOwnershipKind::Owned) {
302
+ svi->setOwnershipKind (ValueOwnershipKind::Guaranteed);
303
+ }
304
+ continue ;
305
+ }
306
+
307
+ if (auto *ofci = dyn_cast<OwnershipForwardingConversionInst>(result)) {
308
+ if (ofci->getOwnershipKind () == ValueOwnershipKind::Owned) {
309
+ ofci->setOwnershipKind (ValueOwnershipKind::Guaranteed);
310
+ }
311
+ continue ;
312
+ }
313
+
314
+ if (auto *sei = dyn_cast<OwnershipForwardingSelectEnumInstBase>(result)) {
315
+ if (sei->getOwnershipKind () == ValueOwnershipKind::Owned) {
316
+ sei->setOwnershipKind (ValueOwnershipKind::Guaranteed);
317
+ }
318
+ continue ;
319
+ }
320
+
321
+ if (auto *mvir = dyn_cast<MultipleValueInstructionResult>(result)) {
322
+ if (mvir->getOwnershipKind () == ValueOwnershipKind::Owned) {
323
+ mvir->setOwnershipKind (ValueOwnershipKind::Guaranteed);
324
+ }
325
+ continue ;
326
+ }
327
+
328
+ llvm_unreachable (" unhandled forwarding instruction?!" );
329
+ }
330
+ }
331
+ }
332
+
201
333
// ===----------------------------------------------------------------------===//
202
334
// Address Written To Analysis
203
335
// ===----------------------------------------------------------------------===//
@@ -321,76 +453,6 @@ bool IsAddressWrittenToDefUseAnalysis::isWrittenToHelper(SILValue initialValue)
321
453
return false ;
322
454
}
323
455
324
- // ===----------------------------------------------------------------------===//
325
- // Convert Forwarding Insts from Owned -> Guaranteed
326
- // ===----------------------------------------------------------------------===//
327
-
328
- static void convertForwardingUsesFromOwnedToGuaranteed (
329
- ArrayRef<Operand *> guaranteedForwardingUses) {
330
- // Then change all of our guaranteed forwarding insts to have guaranteed
331
- // ownership kind instead of what ever they previously had (ignoring trivial
332
- // results);
333
- while (!guaranteedForwardingUses.empty ()) {
334
- auto *use = guaranteedForwardingUses.back ();
335
- guaranteedForwardingUses = guaranteedForwardingUses.drop_back ();
336
-
337
- auto *i = use->getUser ();
338
-
339
- // If this is a term inst, just convert all of its incoming values that are
340
- // owned to be guaranteed.
341
- if (auto *ti = dyn_cast<TermInst>(i)) {
342
- for (auto &succ : ti->getSuccessors ()) {
343
- auto *succBlock = succ.getBB ();
344
-
345
- // If we do not have any arguments, then continue.
346
- if (succBlock->args_empty ())
347
- continue ;
348
-
349
- for (auto *succArg : succBlock->getSILPhiArguments ()) {
350
- // If we have an any value, just continue.
351
- if (succArg->getOwnershipKind () == ValueOwnershipKind::Owned) {
352
- succArg->setOwnershipKind (ValueOwnershipKind::Guaranteed);
353
- }
354
- }
355
- }
356
- continue ;
357
- }
358
-
359
- assert (i->hasResults ());
360
- for (SILValue result : i->getResults ()) {
361
- if (auto *svi = dyn_cast<OwnershipForwardingSingleValueInst>(result)) {
362
- if (svi->getOwnershipKind () == ValueOwnershipKind::Owned) {
363
- svi->setOwnershipKind (ValueOwnershipKind::Guaranteed);
364
- }
365
- continue ;
366
- }
367
-
368
- if (auto *ofci = dyn_cast<OwnershipForwardingConversionInst>(result)) {
369
- if (ofci->getOwnershipKind () == ValueOwnershipKind::Owned) {
370
- ofci->setOwnershipKind (ValueOwnershipKind::Guaranteed);
371
- }
372
- continue ;
373
- }
374
-
375
- if (auto *sei = dyn_cast<OwnershipForwardingSelectEnumInstBase>(result)) {
376
- if (sei->getOwnershipKind () == ValueOwnershipKind::Owned) {
377
- sei->setOwnershipKind (ValueOwnershipKind::Guaranteed);
378
- }
379
- continue ;
380
- }
381
-
382
- if (auto *mvir = dyn_cast<MultipleValueInstructionResult>(result)) {
383
- if (mvir->getOwnershipKind () == ValueOwnershipKind::Owned) {
384
- mvir->setOwnershipKind (ValueOwnershipKind::Guaranteed);
385
- }
386
- continue ;
387
- }
388
-
389
- llvm_unreachable (" unhandled forwarding instruction?!" );
390
- }
391
- }
392
- }
393
-
394
456
// ===----------------------------------------------------------------------===//
395
457
// Implementation
396
458
// ===----------------------------------------------------------------------===//
@@ -473,6 +535,15 @@ struct SemanticARCOptVisitor
473
535
visitedSinceLastMutation.clear ();
474
536
}
475
537
538
+ InstModCallbacks getCallbacks () {
539
+ return InstModCallbacks (
540
+ [this ](SILInstruction *inst) { eraseInstruction (inst); },
541
+ [](SILInstruction *) {}, [](SILValue, SILValue) {},
542
+ [this ](SingleValueInstruction *i, SILValue value) {
543
+ eraseAndRAUWSingleValueInstruction (i, value);
544
+ });
545
+ }
546
+
476
547
// / The default visitor.
477
548
bool visitSILInstruction (SILInstruction *i) {
478
549
assert (!isGuaranteedForwardingInst (i) &&
@@ -808,18 +879,8 @@ bool SemanticARCOptVisitor::performGuaranteedCopyValueOptimization(CopyValueInst
808
879
}
809
880
810
881
// Otherwise, we know that our copy_value/destroy_values are all completely
811
- // within the guaranteed value scope. First delete the destroys/copies.
812
- while (!destroys.empty ()) {
813
- auto *d = destroys.back ();
814
- destroys = destroys.drop_back ();
815
- eraseInstruction (d->getUser ());
816
- ++NumEliminatedInsts;
817
- }
818
-
819
- eraseAndRAUWSingleValueInstruction (cvi, cvi->getOperand ());
820
- convertForwardingUsesFromOwnedToGuaranteed (
821
- lr.getNonConsumingForwardingUses ());
822
-
882
+ // within the guaranteed value scope. So RAUW and convert to guaranteed!
883
+ std::move (lr).convertToGuaranteedAndRAUW (cvi->getOperand (), getCallbacks ());
823
884
++NumEliminatedInsts;
824
885
return true ;
825
886
}
@@ -1291,41 +1352,8 @@ bool SemanticARCOptVisitor::visitLoadInst(LoadInst *li) {
1291
1352
auto *lbi =
1292
1353
SILBuilderWithScope (li).createLoadBorrow (li->getLoc (), li->getOperand ());
1293
1354
1294
- // Since we are looking through forwarding uses that can accept guaranteed
1295
- // parameters, we can have multiple destroy_value along the same path. We need
1296
- // to find the post-dominating block set of these destroy value to ensure that
1297
- // we do not insert multiple end_borrow.
1298
- assert (lifetimeFrontier.empty ());
1299
- ValueLifetimeAnalysis analysis (li, lr.getDestroyingInsts ());
1300
- bool foundCriticalEdges = !analysis.computeFrontier (
1301
- lifetimeFrontier, ValueLifetimeAnalysis::DontModifyCFG,
1302
- &getDeadEndBlocks ());
1303
- (void )foundCriticalEdges;
1304
- assert (!foundCriticalEdges);
1305
- auto loc = RegularLocation::getAutoGeneratedLocation ();
1306
- while (!lifetimeFrontier.empty ()) {
1307
- auto *insertPoint = lifetimeFrontier.pop_back_val ();
1308
- SILBuilderWithScope builder (insertPoint);
1309
- builder.createEndBorrow (loc, lbi);
1310
- }
1311
-
1312
- // Then delete all of our destroy_value.
1313
- auto destroyValues = lr.getDestroyingUses ();
1314
- while (!destroyValues.empty ()) {
1315
- auto *dvi = destroyValues.back ();
1316
- destroyValues = destroyValues.drop_back ();
1317
- eraseInstruction (dvi->getUser ());
1318
- ++NumEliminatedInsts;
1319
- }
1320
-
1321
- // RAUW our other uses from the load to the load_borrow.
1322
- eraseAndRAUWSingleValueInstruction (li, lbi);
1323
-
1324
- // And then change the ownership all of our owned forwarding users to be
1325
- // guaranteed.
1326
- convertForwardingUsesFromOwnedToGuaranteed (
1327
- lr.getNonConsumingForwardingUses ());
1328
-
1355
+ lr.insertEndBorrowsAtDestroys (lbi, getDeadEndBlocks (), lifetimeFrontier);
1356
+ std::move (lr).convertToGuaranteedAndRAUW (lbi, getCallbacks ());
1329
1357
++NumEliminatedInsts;
1330
1358
++NumLoadCopyConvertedToLoadBorrow;
1331
1359
return true ;
0 commit comments