2525#include " swift/Basic/TaggedUnion.h"
2626#include " swift/SIL/BasicBlockDatastructures.h"
2727#include " swift/SIL/Dominance.h"
28+ #include " swift/SIL/OSSALifetimeCompletion.h"
2829#include " swift/SIL/Projection.h"
2930#include " swift/SIL/SILBuilder.h"
3031#include " swift/SIL/SILFunction.h"
@@ -1784,13 +1785,42 @@ void StackAllocationPromoter::promoteAllocationToPhi() {
17841785}
17851786
17861787void StackAllocationPromoter::run () {
1788+ auto *function = asi->getFunction ();
1789+
17871790 // Reduce the number of load/stores in the function to minimum.
17881791 // After this phase we are left with up to one load and store
17891792 // per block and the last store is recorded.
17901793 pruneAllocStackUsage ();
17911794
17921795 // Replace AllocStacks with Phi-nodes.
17931796 promoteAllocationToPhi ();
1797+
1798+ // Make sure that all of the allocations were promoted into registers.
1799+ assert (isWriteOnlyAllocation (asi) && " Non-write uses left behind" );
1800+
1801+ SmallVector<SILValue> valuesToComplete;
1802+
1803+ // Enum types may have incomplete lifetimes in address form, when promoted to
1804+ // value form after mem2reg, they will end up with incomplete ossa lifetimes.
1805+ // Use the lifetime completion utility to complete such lifetimes.
1806+ // First, collect the stored values to complete.
1807+ if (asi->getType ().isOrHasEnum ()) {
1808+ for (auto it : initializationPoints) {
1809+ auto *si = it.second ;
1810+ auto src = si->getOperand (0 );
1811+ valuesToComplete.push_back (src);
1812+ }
1813+ }
1814+
1815+ // ... and erase the allocation.
1816+ deleter.forceDeleteWithUsers (asi);
1817+
1818+ // Now, complete lifetimes!
1819+ OSSALifetimeCompletion completion (function, domInfo);
1820+
1821+ for (auto it : valuesToComplete) {
1822+ completion.completeOSSALifetime (it);
1823+ }
17941824}
17951825
17961826// ===----------------------------------------------------------------------===//
@@ -2091,12 +2121,31 @@ bool MemoryToRegisters::promoteSingleAllocation(AllocStackInst *alloc) {
20912121 deleter.forceDeleteWithUsers (alloc);
20922122 return true ;
20932123 } else {
2094- // For enums we require that all uses are in the same block.
2095- // Otherwise there could be a switch_enum of an optional where the none-case
2096- // does not have a destroy of the enum value.
2097- // After transforming such an alloc_stack, the value would leak in the none-
2098- // case block.
2099- if (f.hasOwnership () && alloc->getType ().isOrHasEnum ())
2124+ auto enableOptimizationForEnum = [](AllocStackInst *asi) {
2125+ if (asi->isLexical ()) {
2126+ return false ;
2127+ }
2128+ for (auto *use : asi->getUses ()) {
2129+ auto *user = use->getUser ();
2130+ if (!isa<StoreInst>(user) && !isa<StoreBorrowInst>(user)) {
2131+ continue ;
2132+ }
2133+ auto stored = user->getOperand (CopyLikeInstruction::Src);
2134+ if (stored->isLexical ()) {
2135+ return false ;
2136+ }
2137+ }
2138+ return true ;
2139+ };
2140+ // For stack locs of enum type that are lexical or with lexical stored
2141+ // values, we require that all uses are in the same block. This is because
2142+ // we can have incomplete lifetime of enum typed addresses, and on
2143+ // converting to value form this causes verification error. For all other
2144+ // stack locs of enum type, we use the lifetime completion utility to fix
2145+ // the lifetime. But when we have a lexical value, the utility can complete
2146+ // lifetimes on dead end blocks only.
2147+ if (f.hasOwnership () && alloc->getType ().isOrHasEnum () &&
2148+ !enableOptimizationForEnum (alloc))
21002149 return false ;
21012150 }
21022151
@@ -2108,11 +2157,6 @@ bool MemoryToRegisters::promoteSingleAllocation(AllocStackInst *alloc) {
21082157 StackAllocationPromoter (alloc, domInfo, domTreeLevels, ctx, deleter,
21092158 instructionsToDelete)
21102159 .run ();
2111-
2112- // Make sure that all of the allocations were promoted into registers.
2113- assert (isWriteOnlyAllocation (alloc) && " Non-write uses left behind" );
2114- // ... and erase the allocation.
2115- deleter.forceDeleteWithUsers (alloc);
21162160 return true ;
21172161}
21182162
0 commit comments