26
26
#include " swift/SIL/BasicBlockDatastructures.h"
27
27
#include " swift/SIL/Dominance.h"
28
28
#include " swift/SIL/Projection.h"
29
+ #include " swift/SIL/OSSALifetimeCompletion.h"
29
30
#include " swift/SIL/SILBuilder.h"
30
31
#include " swift/SIL/SILFunction.h"
31
32
#include " swift/SIL/SILInstruction.h"
@@ -1784,13 +1785,42 @@ void StackAllocationPromoter::promoteAllocationToPhi() {
1784
1785
}
1785
1786
1786
1787
void StackAllocationPromoter::run () {
1788
+ auto *function = asi->getFunction ();
1789
+
1787
1790
// Reduce the number of load/stores in the function to minimum.
1788
1791
// After this phase we are left with up to one load and store
1789
1792
// per block and the last store is recorded.
1790
1793
pruneAllocStackUsage ();
1791
1794
1792
1795
// Replace AllocStacks with Phi-nodes.
1793
1796
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
+ }
1794
1824
}
1795
1825
1796
1826
// ===----------------------------------------------------------------------===//
@@ -2091,12 +2121,16 @@ bool MemoryToRegisters::promoteSingleAllocation(AllocStackInst *alloc) {
2091
2121
deleter.forceDeleteWithUsers (alloc);
2092
2122
return true ;
2093
2123
} 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
+ // For lexical stack locs with enum type, we require that all uses are in
2125
+ // the same block. Otherwise there could be a switch_enum of an optional
2126
+ // where the none-case does not have a destroy of the enum value. After
2127
+ // transforming such an alloc_stack, the value would leak in the none- case
2128
+ // block.
2129
+ // For non-lexical stack locs, we use the lifetime completion utility
2130
+ // to fix this, but for lexical stack locs, we may create move_value
2131
+ // [lexical] whose lifetime is not completed since the utility depends on
2132
+ // the presence of unreachable blocks.
2133
+ if (f.hasOwnership () && alloc->isLexical () && alloc->getType ().isOrHasEnum ())
2100
2134
return false ;
2101
2135
}
2102
2136
@@ -2108,11 +2142,6 @@ bool MemoryToRegisters::promoteSingleAllocation(AllocStackInst *alloc) {
2108
2142
StackAllocationPromoter (alloc, domInfo, domTreeLevels, ctx, deleter,
2109
2143
instructionsToDelete)
2110
2144
.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);
2116
2145
return true ;
2117
2146
}
2118
2147
0 commit comments