@@ -195,6 +195,13 @@ class LiveValues {
195195 return LiveValues::forOwned ({stored, move});
196196 }
197197
198+ static LiveValues forValues (SILValue stored, SILValue lexical) {
199+ if (stored->getOwnershipKind () == OwnershipKind::Guaranteed) {
200+ return LiveValues::forGuaranteed ({stored, lexical});
201+ }
202+ return LiveValues::forOwned ({stored, lexical});
203+ }
204+
198205 static LiveValues toReplace (AllocStackInst *asi, SILValue replacement) {
199206 if (replacement->getOwnershipKind () == OwnershipKind::Guaranteed) {
200207 return LiveValues::forGuaranteed (Guaranteed::toReplace (asi, replacement));
@@ -715,6 +722,27 @@ static bool canEndLexicalLifetime(LiveValues values) {
715722 return values.canEndLexicalLifetime ();
716723}
717724
725+ static SILValue getLexicalValueForStore (SILInstruction *inst,
726+ AllocStackInst *asi) {
727+ assert (isa<StoreInst>(inst) || isa<StoreBorrowInst>(inst));
728+
729+ SILValue stored = inst->getOperand (CopyLikeInstruction::Src);
730+ LLVM_DEBUG (llvm::dbgs () << " *** Found Store def " << stored);
731+
732+ if (!lexicalLifetimeEnsured (asi)) {
733+ return SILValue ();
734+ }
735+ if (isa<StoreBorrowInst>(inst)) {
736+ if (isGuaranteedLexicalValue (stored)) {
737+ return SILValue ();
738+ }
739+ auto borrow = cast<BeginBorrowInst>(inst->getNextInstruction ());
740+ return borrow;
741+ }
742+ auto move = cast<MoveValueInst>(inst->getNextInstruction ());
743+ return move;
744+ }
745+
718746// / Begin a lexical borrow scope for the value stored into the provided
719747// / StoreInst after that instruction.
720748// /
@@ -1233,27 +1261,9 @@ StackAllocationPromoter::getLiveOutValues(BlockSetVector &phiBlocks,
12331261 BlockToInstMap::iterator it = initializationPoints.find (domBlock);
12341262 if (it != initializationPoints.end ()) {
12351263 auto *inst = it->second ;
1236- assert (isa<StoreInst>(inst) || isa<StoreBorrowInst>(inst));
1237-
1238- SILValue stored = inst->getOperand (CopyLikeInstruction::Src);
1239- LLVM_DEBUG (llvm::dbgs () << " *** Found Store def " << stored);
1240-
1241- if (!lexicalLifetimeEnsured (asi)) {
1242- auto values = LiveValues::forOwned (stored, {});
1243- return values;
1244- }
1245- if (isa<StoreBorrowInst>(inst)) {
1246- if (isGuaranteedLexicalValue (stored)) {
1247- auto values = LiveValues::forGuaranteed (stored, {});
1248- return values;
1249- }
1250- auto borrow = cast<BeginBorrowInst>(inst->getNextInstruction ());
1251- auto values = LiveValues::forGuaranteed (stored, borrow);
1252- return values;
1253- }
1254- auto move = cast<MoveValueInst>(inst->getNextInstruction ());
1255- auto values = LiveValues::forOwned (stored, move);
1256- return values;
1264+ auto stored = inst->getOperand (CopyLikeInstruction::Src);
1265+ auto lexical = getLexicalValueForStore (inst, asi);
1266+ return LiveValues::forValues (stored, lexical);
12571267 }
12581268
12591269 // If there is a Phi definition in this block:
@@ -1806,8 +1816,13 @@ void StackAllocationPromoter::run() {
18061816 if (asi->getType ().isOrHasEnum ()) {
18071817 for (auto it : initializationPoints) {
18081818 auto *si = it.second ;
1809- auto src = si->getOperand (0 );
1810- valuesToComplete.push_back (src);
1819+ auto stored = si->getOperand (CopyLikeInstruction::Src);
1820+ valuesToComplete.push_back (stored);
1821+ if (lexicalLifetimeEnsured (asi)) {
1822+ if (auto lexical = getLexicalValueForStore (si, asi)) {
1823+ valuesToComplete.push_back (lexical);
1824+ }
1825+ }
18111826 }
18121827 }
18131828
@@ -1817,8 +1832,12 @@ void StackAllocationPromoter::run() {
18171832 // Now, complete lifetimes!
18181833 OSSALifetimeCompletion completion (function, domInfo);
18191834
1835+ // We may have incomplete lifetimes for enum locations on trivial paths.
1836+ // After promoting them, complete lifetime here.
18201837 for (auto it : valuesToComplete) {
1821- completion.completeOSSALifetime (it);
1838+ // Set forceBoundaryCompletion as true so that we complete at boundary for
1839+ // lexical values as well.
1840+ completion.completeOSSALifetime (it, /* forceBoundaryCompletion */ true );
18221841 }
18231842}
18241843
@@ -2119,33 +2138,6 @@ bool MemoryToRegisters::promoteSingleAllocation(AllocStackInst *alloc) {
21192138 << *alloc);
21202139 deleter.forceDeleteWithUsers (alloc);
21212140 return true ;
2122- } else {
2123- auto enableOptimizationForEnum = [](AllocStackInst *asi) {
2124- if (asi->isLexical ()) {
2125- return false ;
2126- }
2127- for (auto *use : asi->getUses ()) {
2128- auto *user = use->getUser ();
2129- if (!isa<StoreInst>(user) && !isa<StoreBorrowInst>(user)) {
2130- continue ;
2131- }
2132- auto stored = user->getOperand (CopyLikeInstruction::Src);
2133- if (stored->isLexical ()) {
2134- return false ;
2135- }
2136- }
2137- return true ;
2138- };
2139- // For stack locs of enum type that are lexical or with lexical stored
2140- // values, we require that all uses are in the same block. This is because
2141- // we can have incomplete lifetime of enum typed addresses, and on
2142- // converting to value form this causes verification error. For all other
2143- // stack locs of enum type, we use the lifetime completion utility to fix
2144- // the lifetime. But when we have a lexical value, the utility can complete
2145- // lifetimes on dead end blocks only.
2146- if (f.hasOwnership () && alloc->getType ().isOrHasEnum () &&
2147- !enableOptimizationForEnum (alloc))
2148- return false ;
21492141 }
21502142
21512143 LLVM_DEBUG (llvm::dbgs () << " *** Need to insert BB arguments for " << *alloc);
0 commit comments