@@ -297,13 +297,28 @@ static void cleanupOperandsBeforeDeletion(SILInstruction *oldValue,
297297// directly checking ownership requirements. This does not determine whether the
298298// scope of the newValue can be fully extended.
299299bool OwnershipRAUWHelper::hasValidRAUWOwnership (SILValue oldValue,
300- SILValue newValue) {
300+ SILValue newValue,
301+ ArrayRef<Operand *> oldUses) {
301302 auto newOwnershipKind = newValue.getOwnershipKind ();
302303
303304 // If the either value is lexical, replacing its uses may result in
304305 // shortening or lengthening its lifetime in ways that don't respect lexical
305306 // scope and deinit barriers.
306- if (oldValue->isLexical () || newValue->isLexical ())
307+ //
308+ // Specifically, we have the following cases:
309+ //
310+ // +--------+--------+
311+ // |oldValue|newValue|
312+ // +--------+--------+
313+ // | not | not | legal
314+ // +--------+--------+
315+ // |lexical | not | illegal
316+ // +--------+--------+
317+ // | * |lexical | legal so long as it doesn't extend newValue's lifetime
318+ // +--------+--------+
319+ if ((oldValue->isLexical () && !newValue->isLexical ()) ||
320+ (newValue->isLexical () &&
321+ !areUsesWithinLexicalValueLifetime (newValue, oldUses)))
307322 return false ;
308323
309324 // If our new kind is ValueOwnershipKind::None, then we are fine. We
@@ -353,20 +368,51 @@ bool OwnershipRAUWHelper::hasValidRAUWOwnership(SILValue oldValue,
353368// extend the lifetime of \p oldValue to cover the new uses.
354369static bool canFixUpOwnershipForRAUW (SILValue oldValue, SILValue newValue,
355370 OwnershipFixupContext &context) {
356- if (!OwnershipRAUWHelper::hasValidRAUWOwnership (oldValue, newValue))
357- return false ;
371+ switch (oldValue.getOwnershipKind ()) {
372+ case OwnershipKind::Guaranteed:
373+ // Check that the old lifetime can be extended and record the necessary
374+ // book-keeping in the OwnershipFixupContext.
375+ context.clear ();
376+
377+ // Check that no transitive uses have a PointerEscape, and record the leaf
378+ // uses for liveness extension.
379+ if (!findExtendedTransitiveGuaranteedUses (oldValue,
380+ context.guaranteedUsePoints ))
381+ return false ;
382+ return OwnershipRAUWHelper::hasValidRAUWOwnership (
383+ oldValue, newValue, context.guaranteedUsePoints );
384+ default : {
385+ SmallVector<Operand *, 8 > ownedUsePoints;
386+ // If newValue is lexical, find the uses of oldValue so that it can be
387+ // determined whether the replacement would illegally extend the lifetime
388+ // of newValue.
389+ if (newValue->isLexical () &&
390+ !findUsesOfSimpleValue (oldValue, &ownedUsePoints))
391+ return false ;
392+ return OwnershipRAUWHelper::hasValidRAUWOwnership (oldValue, newValue,
393+ ownedUsePoints);
394+ }
395+ }
396+ }
397+
398+ bool swift::areUsesWithinLexicalValueLifetime (SILValue value,
399+ ArrayRef<Operand *> uses) {
400+ assert (value->isLexical ());
358401
359- if (oldValue.getOwnershipKind () != OwnershipKind::Guaranteed)
402+ // The lexical lifetime of a function argument is the whole body of the
403+ // function.
404+ if (isa<SILFunctionArgument>(value))
360405 return true ;
361406
362- // Check that the old lifetime can be extended and record the necessary
363- // book-keeping in the OwnershipFixupContext.
364- context.clear ();
407+ if (auto borrowedValue = BorrowedValue (value)) {
408+ PrunedLiveness liveness;
409+ auto *function = value->getFunction ();
410+ borrowedValue.computeLiveness (liveness);
411+ DeadEndBlocks deadEndBlocks (function);
412+ return liveness.areUsesWithinBoundary (uses, &deadEndBlocks);
413+ }
365414
366- // Check that no transitive uses have a PointerEscape, and record the leaf
367- // uses for liveness extension.
368- return findExtendedTransitiveGuaranteedUses (oldValue,
369- context.guaranteedUsePoints );
415+ return false ;
370416}
371417
372418// ===----------------------------------------------------------------------===//
@@ -1118,7 +1164,9 @@ SILValue OwnershipRAUWPrepare::prepareReplacement(SILValue newValue) {
11181164 if (oldValue->use_empty ())
11191165 return newValue;
11201166
1121- assert (OwnershipRAUWHelper::hasValidRAUWOwnership (oldValue, newValue) &&
1167+ assert (
1168+ OwnershipRAUWHelper::hasValidRAUWOwnership (oldValue, newValue,
1169+ ctx.guaranteedUsePoints ) &&
11221170 " Should have checked if can perform this operation before calling it?!" );
11231171 // If our new value is just none, we can pass anything to it so just RAUW
11241172 // and return.
@@ -1576,7 +1624,10 @@ OwnershipReplaceSingleUseHelper::OwnershipReplaceSingleUseHelper(
15761624
15771625 // Otherwise, lets check if we can perform this RAUW operation. If we can't,
15781626 // set ctx to nullptr to invalidate the helper and return.
1579- if (!OwnershipRAUWHelper::hasValidRAUWOwnership (use->get (), newValue)) {
1627+ SmallVector<Operand *, 1 > oldUses;
1628+ oldUses.push_back (use);
1629+ if (!OwnershipRAUWHelper::hasValidRAUWOwnership (use->get (), newValue,
1630+ oldUses)) {
15801631 invalidate ();
15811632 return ;
15821633 }
0 commit comments