@@ -57,6 +57,7 @@ STATISTIC(NumInstRemoved, "Number of Instructions removed");
5757
5858static bool lexicalLifetimeEnsured (AllocStackInst *asi);
5959static bool isGuaranteedLexicalValue (SILValue src);
60+ static bool isOwnedLexicalValue (SILValue src);
6061
6162namespace {
6263
@@ -96,9 +97,11 @@ class LiveValues {
9697 if (!lexicalLifetimeEnsured (asi)) {
9798 return stored;
9899 }
99- // We should have created a move of the @owned stored value.
100- assert (move);
101- return move;
100+ auto storedIsLexical = stored && isOwnedLexicalValue (stored);
101+ // If the value was already lexical, we use it directly. Otherwise, a new
102+ // move_value [lexical] is used.
103+ assert (storedIsLexical || move);
104+ return storedIsLexical ? stored : move;
102105 }
103106
104107 bool canEndLexicalLifetime () {
@@ -107,7 +110,8 @@ class LiveValues {
107110 // to end a lexical lifetime. In that case, the lifetime end will be
108111 // added later, when we have enough information, namely the live in
109112 // values, to end it.
110- return move;
113+ auto storedIsLexical = stored && isOwnedLexicalValue (stored);
114+ return storedIsLexical ? stored : move;
111115 }
112116 };
113117 struct Guaranteed {
@@ -221,6 +225,7 @@ class LiveValues {
221225 return guaranteed.stored ;
222226 }
223227
228+ // / Whether it's possible and appropriate to end the lifetime.
224229 bool canEndLexicalLifetime () {
225230 if (auto *owned = storage.dyn_cast <Owned>()) {
226231 return owned->canEndLexicalLifetime ();
@@ -521,16 +526,15 @@ static bool lexicalLifetimeEnsured(AllocStackInst *asi) {
521526 !asi->getElementType ().isTrivial (*asi->getFunction ());
522527}
523528
529+ static bool isOwnedLexicalValue (SILValue src) {
530+ return src->getOwnershipKind () == OwnershipKind::Owned && src->isLexical ();
531+ }
532+
524533static bool isGuaranteedLexicalValue (SILValue src) {
525534 return src->getOwnershipKind () == OwnershipKind::Guaranteed &&
526535 src->isLexical ();
527536}
528537
529- // / Returns true if we have enough information to end the lifetime.
530- static bool canEndLexicalLifetime (LiveValues values) {
531- return values.canEndLexicalLifetime ();
532- }
533-
534538// / Begin a lexical borrow scope for the value stored into the provided
535539// / StoreInst after that instruction.
536540// /
@@ -546,6 +550,9 @@ beginOwnedLexicalLifetimeAfterStore(AllocStackInst *asi, StoreInst *inst) {
546550 SILValue stored = inst->getOperand (CopyLikeInstruction::Src);
547551 SILLocation loc = RegularLocation::getAutoGeneratedLocation (inst->getLoc ());
548552
553+ if (isOwnedLexicalValue (stored)) {
554+ return {LiveValues::forOwned (stored, {}), /* isStorageValid*/ true };
555+ }
549556 MoveValueInst *mvi = nullptr ;
550557 SILBuilderWithScope::insertAfter (inst, [&](SILBuilder &builder) {
551558 mvi = builder.createMoveValue (loc, stored, /* isLexical*/ true );
@@ -825,7 +832,7 @@ SILInstruction *StackAllocationPromoter::promoteAllocationInBlock(
825832 if (lexicalLifetimeEnsured (asi)) {
826833 // End the lexical lifetime at a load [take]. The storage is no
827834 // longer keeping the value alive.
828- if (runningVals && canEndLexicalLifetime ( runningVals->value )) {
835+ if (runningVals && runningVals->value . canEndLexicalLifetime ( )) {
829836 // End it right now if we have enough information.
830837 endOwnedLexicalLifetimeBeforeInst (asi, /* beforeInstruction=*/ li,
831838 ctx,
@@ -908,7 +915,7 @@ SILInstruction *StackAllocationPromoter::promoteAllocationInBlock(
908915 lastStoreInst = si;
909916 if (lexicalLifetimeEnsured (asi)) {
910917 if (oldRunningVals && oldRunningVals->isStorageValid &&
911- canEndLexicalLifetime ( oldRunningVals->value )) {
918+ oldRunningVals->value . canEndLexicalLifetime ( )) {
912919 endOwnedLexicalLifetimeBeforeInst (asi, /* beforeInstruction=*/ si, ctx,
913920 oldRunningVals->value .getOwned ());
914921 }
@@ -965,7 +972,7 @@ SILInstruction *StackAllocationPromoter::promoteAllocationInBlock(
965972 }
966973 // Mark storage as invalid and mark end_borrow as a deinit point.
967974 runningVals->isStorageValid = false ;
968- if (!canEndLexicalLifetime ( runningVals->value )) {
975+ if (!runningVals->value . canEndLexicalLifetime ( )) {
969976 continue ;
970977 }
971978 endGuaranteedLexicalLifetimeBeforeInst (
@@ -1067,6 +1074,10 @@ StackAllocationPromoter::getLiveOutValues(BlockSetVector &phiBlocks,
10671074 auto values = LiveValues::forGuaranteed (stored, borrow);
10681075 return values;
10691076 }
1077+ if (isOwnedLexicalValue (stored)) {
1078+ auto values = LiveValues::forOwned (stored, {});
1079+ return values;
1080+ }
10701081 auto move = cast<MoveValueInst>(inst->getNextInstruction ());
10711082 auto values = LiveValues::forOwned (stored, move);
10721083 return values;
@@ -1422,7 +1433,7 @@ void StackAllocationPromoter::endLexicalLifetime(BlockSetVector &phiBlocks) {
14221433 if (isa<EndBorrowInst>(inst)) {
14231434 // Not all store_borrows will have a begin_borrow [lexical] that needs
14241435 // to be ended. If the source is already lexical, we don't create it.
1425- if (!canEndLexicalLifetime (*values )) {
1436+ if (!values-> canEndLexicalLifetime ()) {
14261437 continue ;
14271438 }
14281439 endGuaranteedLexicalLifetimeBeforeInst (
@@ -1445,7 +1456,7 @@ void StackAllocationPromoter::endLexicalLifetime(BlockSetVector &phiBlocks) {
14451456 if (terminatesInUnreachable || uniqueSuccessorLacksLiveInValues ()) {
14461457 auto values = getLiveOutValues (phiBlocks, bb);
14471458 if (values->isGuaranteed ()) {
1448- if (!canEndLexicalLifetime (*values )) {
1459+ if (!values-> canEndLexicalLifetime ()) {
14491460 continue ;
14501461 }
14511462 endGuaranteedLexicalLifetimeBeforeInst (
@@ -1971,7 +1982,7 @@ void MemoryToRegisters::removeSingleBlockAllocation(AllocStackInst *asi) {
19711982 continue ;
19721983 }
19731984 runningVals->isStorageValid = false ;
1974- if (!canEndLexicalLifetime ( runningVals->value )) {
1985+ if (!runningVals->value . canEndLexicalLifetime ( )) {
19751986 continue ;
19761987 }
19771988 endGuaranteedLexicalLifetimeBeforeInst (
0 commit comments