|
28 | 28 | #include "swift/SIL/SILBuilder.h"
|
29 | 29 | #include "swift/SIL/SILInstruction.h"
|
30 | 30 | #include "swift/SILOptimizer/Utils/CFGOptUtils.h"
|
| 31 | +#include "swift/SILOptimizer/Utils/InstOptUtils.h" |
31 | 32 | #include "swift/SILOptimizer/Utils/ValueLifetime.h"
|
32 | 33 |
|
33 | 34 | using namespace swift;
|
@@ -167,39 +168,48 @@ namespace {
|
167 | 168 | struct OwnershipLifetimeExtender {
|
168 | 169 | OwnershipFixupContext &ctx;
|
169 | 170 |
|
170 |
| - /// Lifetime extend newValue over owned oldValue assuming that our copy will |
171 |
| - /// have its lifetime ended by oldValue's lifetime ending uses after RAUWing. |
172 |
| - CopyValueInst * |
173 |
| - copyAndExtendForLifetimeEndingRAUW(SILValue value, |
174 |
| - SILInstruction *consumingPoint); |
175 |
| - |
176 |
| - CopyValueInst * |
177 |
| - copyAndExtendForNonLifetimeEndingRAUW(SILValue value, |
178 |
| - ArrayRef<Operand *> range) { |
179 |
| - return copyAndExtendForNonLifetimeEndingRAUW<ArrayRef<Operand *>>(value, |
180 |
| - range); |
| 171 | + /// Create a new copy of \p value assuming that our caller will clean up the |
| 172 | + /// copy along all paths that go through consuming point. Operationally this |
| 173 | + /// means that the API will insert compensating destroy_value on the copy |
| 174 | + /// along all paths that do not go through consuming point. |
| 175 | + /// |
| 176 | + /// DISCUSSION: If \p consumingPoint is an instruction that forwards \p value, |
| 177 | + /// calling this and then RAUWing with \p value guarantee that \p value will |
| 178 | + /// be consumed by the forwarding instruction's results consuming uses. |
| 179 | + CopyValueInst *createPlusOneCopy(SILValue value, |
| 180 | + SILInstruction *consumingPoint); |
| 181 | + |
| 182 | + /// Create a copy of \p value that covers all of \p range and insert all |
| 183 | + /// needed destroy_values. We assume that no uses in \p range consume \p |
| 184 | + /// value. |
| 185 | + CopyValueInst *createPlusZeroCopy(SILValue value, ArrayRef<Operand *> range) { |
| 186 | + return createPlusZeroCopy<ArrayRef<Operand *>>(value, range); |
181 | 187 | }
|
182 | 188 |
|
| 189 | + /// Create a copy of \p value that covers all of \p range and insert all |
| 190 | + /// needed destroy_values. We assume that all uses in \p range do not consume |
| 191 | + /// \p value. |
| 192 | + /// |
| 193 | + /// We return our copy_value to the user at +0 to show that they do not need |
| 194 | + /// to insert cleanup destroys. |
183 | 195 | template <typename RangeTy>
|
184 |
| - CopyValueInst *copyAndExtendForNonLifetimeEndingRAUW(SILValue value, |
185 |
| - const RangeTy &range); |
| 196 | + CopyValueInst *createPlusZeroCopy(SILValue value, const RangeTy &range); |
186 | 197 |
|
| 198 | + /// Create a new borrow scope for \p newValue that contains all uses in \p |
| 199 | + /// useRange. We assume that \p useRange does not contain any lifetime ending |
| 200 | + /// uses. |
187 | 201 | template <typename RangeTy>
|
188 |
| - BeginBorrowInst *copyBorrowAndExtendForRAUW(SILValue newValue, |
189 |
| - RangeTy useRange); |
190 |
| - |
191 |
| - /// We are copy/borrowing new value to be over the same lifetime as old |
192 |
| - /// value. We know that oldValue is dominated by newValue. |
193 |
| - BeginBorrowInst *copyBorrowAndExtendForLifetimeEndingRAUW(SILValue newValue, |
194 |
| - SILValue oldValue); |
| 202 | + BeginBorrowInst *createPlusZeroBorrow(SILValue newValue, RangeTy useRange); |
195 | 203 | };
|
196 | 204 |
|
197 | 205 | } // end anonymous namespace
|
198 | 206 |
|
199 |
| -/// Lifetime extend newValue over owned oldValue assuming that our copy will |
200 |
| -/// have its lifetime ended by oldValue's lifetime ending uses after RAUWing. |
201 |
| -CopyValueInst *OwnershipLifetimeExtender::copyAndExtendForLifetimeEndingRAUW( |
202 |
| - SILValue value, SILInstruction *consumingPoint) { |
| 207 | +// Lifetime extend newValue over owned oldValue assuming that our copy will have |
| 208 | +// its lifetime ended by oldValue's lifetime ending uses after RAUWing by our |
| 209 | +// caller. |
| 210 | +CopyValueInst * |
| 211 | +OwnershipLifetimeExtender::createPlusOneCopy(SILValue value, |
| 212 | + SILInstruction *consumingPoint) { |
203 | 213 | auto *newValInsertPt = value->getDefiningInsertionPoint();
|
204 | 214 | assert(newValInsertPt);
|
205 | 215 | CopyValueInst *copy;
|
@@ -242,9 +252,12 @@ CopyValueInst *OwnershipLifetimeExtender::copyAndExtendForLifetimeEndingRAUW(
|
242 | 252 | return result;
|
243 | 253 | }
|
244 | 254 |
|
| 255 | +// A copy_value that we lifetime extend with destroy_value over range. We assume |
| 256 | +// all instructions passed into range do not consume value. |
245 | 257 | template <typename RangeTy>
|
246 |
| -CopyValueInst *OwnershipLifetimeExtender::copyAndExtendForNonLifetimeEndingRAUW( |
247 |
| - SILValue value, const RangeTy &range) { |
| 258 | +CopyValueInst * |
| 259 | +OwnershipLifetimeExtender::createPlusZeroCopy(SILValue value, |
| 260 | + const RangeTy &range) { |
248 | 261 | auto *newValInsertPt = value->getDefiningInsertionPoint();
|
249 | 262 | assert(newValInsertPt);
|
250 | 263 |
|
@@ -281,8 +294,8 @@ CopyValueInst *OwnershipLifetimeExtender::copyAndExtendForNonLifetimeEndingRAUW(
|
281 | 294 |
|
282 | 295 | template <typename RangeTy>
|
283 | 296 | BeginBorrowInst *
|
284 |
| -OwnershipLifetimeExtender::copyBorrowAndExtendForRAUW(SILValue newValue, |
285 |
| - RangeTy useRange) { |
| 297 | +OwnershipLifetimeExtender::createPlusZeroBorrow(SILValue newValue, |
| 298 | + RangeTy useRange) { |
286 | 299 | auto *newValInsertPt = newValue->getDefiningInsertionPoint();
|
287 | 300 | assert(newValInsertPt);
|
288 | 301 |
|
@@ -326,52 +339,6 @@ OwnershipLifetimeExtender::copyBorrowAndExtendForRAUW(SILValue newValue,
|
326 | 339 | return borrow;
|
327 | 340 | }
|
328 | 341 |
|
329 |
| -/// We are copy/borrowing new value to be over the same lifetime as old |
330 |
| -/// value. We know that oldValue is dominated by newValue. |
331 |
| -BeginBorrowInst * |
332 |
| -OwnershipLifetimeExtender::copyBorrowAndExtendForLifetimeEndingRAUW( |
333 |
| - SILValue newValue, SILValue oldValue) { |
334 |
| - auto *newValInsertPt = newValue->getDefiningInsertionPoint(); |
335 |
| - assert(newValInsertPt); |
336 |
| - |
337 |
| - CopyValueInst *copy = nullptr; |
338 |
| - if (!isa<SILArgument>(newValue)) { |
339 |
| - SILBuilderWithScope::insertAfter(newValInsertPt, [&](SILBuilder &builder) { |
340 |
| - auto loc = builder.getInsertionPointLoc(); |
341 |
| - copy = builder.createCopyValue(loc, newValue); |
342 |
| - }); |
343 |
| - } else { |
344 |
| - SILBuilderWithScope builder(newValInsertPt); |
345 |
| - auto loc = newValInsertPt->getLoc(); |
346 |
| - copy = builder.createCopyValue(loc, newValue); |
347 |
| - } |
348 |
| - |
349 |
| - // Then insert the begin_borrow at the old value point. We are going to RAUW |
350 |
| - // this in our caller. |
351 |
| - auto *oldValInsertPt = oldValue->getDefiningInsertionPoint(); |
352 |
| - assert(oldValInsertPt); |
353 |
| - auto *borrow = SILBuilderWithScope(oldValInsertPt) |
354 |
| - .createBeginBorrow(oldValInsertPt->getLoc(), copy); |
355 |
| - |
356 |
| - auto &callbacks = ctx.callbacks; |
357 |
| - callbacks.createdNewInst(borrow); |
358 |
| - |
359 |
| - ValueLifetimeAnalysis lifetimeAnalysis(copy, oldValue->getUses()); |
360 |
| - decltype(lifetimeAnalysis)::Frontier frontier; |
361 |
| - bool result = lifetimeAnalysis.computeFrontier( |
362 |
| - frontier, ValueLifetimeAnalysis::DontModifyCFG, &ctx.deBlocks); |
363 |
| - assert(result); |
364 |
| - |
365 |
| - while (!frontier.empty()) { |
366 |
| - auto *insertPt = frontier.pop_back_val(); |
367 |
| - SILBuilderWithScope frontierBuilder(insertPt); |
368 |
| - auto *dvi = frontierBuilder.createDestroyValue(insertPt->getLoc(), copy); |
369 |
| - callbacks.createdNewInst(dvi); |
370 |
| - } |
371 |
| - |
372 |
| - return borrow; |
373 |
| -} |
374 |
| - |
375 | 342 | //===----------------------------------------------------------------------===//
|
376 | 343 | // Reborrow Elimination
|
377 | 344 | //===----------------------------------------------------------------------===//
|
@@ -577,7 +544,7 @@ SILBasicBlock::iterator OwnershipRAUWUtility::handleUnowned() {
|
577 | 544 | }
|
578 | 545 | auto extender = getLifetimeExtender();
|
579 | 546 | SILValue borrow =
|
580 |
| - extender.copyBorrowAndExtendForRAUW(newValue, oldValue->getUses()); |
| 547 | + extender.createPlusZeroBorrow(newValue, oldValue->getUses()); |
581 | 548 | SILBuilderWithScope builder(oldValue);
|
582 | 549 | auto *newInst = builder.createUncheckedOwnershipConversion(
|
583 | 550 | oldValue->getLoc(), borrow, OwnershipKind::Unowned);
|
@@ -608,8 +575,7 @@ SILBasicBlock::iterator OwnershipRAUWUtility::handleUnowned() {
|
608 | 575 | }
|
609 | 576 | }
|
610 | 577 | auto extender = getLifetimeExtender();
|
611 |
| - SILValue copy = extender.copyAndExtendForNonLifetimeEndingRAUW( |
612 |
| - newValue, oldValue->getUses()); |
| 578 | + SILValue copy = extender.createPlusZeroCopy(newValue, oldValue->getUses()); |
613 | 579 | SILBuilderWithScope builder(oldValue);
|
614 | 580 | auto *newInst = builder.createUncheckedOwnershipConversion(
|
615 | 581 | oldValue->getLoc(), copy, OwnershipKind::Unowned);
|
@@ -644,8 +610,7 @@ SILBasicBlock::iterator OwnershipRAUWUtility::handleGuaranteed() {
|
644 | 610 |
|
645 | 611 | auto extender = getLifetimeExtender();
|
646 | 612 | SILValue newBorrowedValue =
|
647 |
| - extender.copyBorrowAndExtendForRAUW<ArrayRef<Operand *>>(newValue, |
648 |
| - usePoints); |
| 613 | + extender.createPlusZeroBorrow<ArrayRef<Operand *>>(newValue, usePoints); |
649 | 614 |
|
650 | 615 | // Now we need to handle reborrows by eliminating the reborrows from any
|
651 | 616 | // borrowing operands that use old value as well as from oldvalue itself. We
|
@@ -706,8 +671,7 @@ SILBasicBlock::iterator OwnershipRAUWUtility::perform() {
|
706 | 671 | // lifetimeEnding RAUW, then RAUW the value, and insert a destroy_value on
|
707 | 672 | // the original value.
|
708 | 673 | auto extender = getLifetimeExtender();
|
709 |
| - SILValue copy = |
710 |
| - extender.copyAndExtendForLifetimeEndingRAUW(newValue, oldValue); |
| 674 | + SILValue copy = extender.createPlusOneCopy(newValue, oldValue); |
711 | 675 | cleanupOperandsBeforeDeletion(oldValue, ctx.callbacks);
|
712 | 676 | auto result = replaceAllUsesAndErase(oldValue, copy, ctx.callbacks);
|
713 | 677 | return result;
|
|
0 commit comments