@@ -195,6 +195,13 @@ class LiveValues {
195
195
return LiveValues::forOwned ({stored, move});
196
196
}
197
197
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
+
198
205
static LiveValues toReplace (AllocStackInst *asi, SILValue replacement) {
199
206
if (replacement->getOwnershipKind () == OwnershipKind::Guaranteed) {
200
207
return LiveValues::forGuaranteed (Guaranteed::toReplace (asi, replacement));
@@ -715,6 +722,27 @@ static bool canEndLexicalLifetime(LiveValues values) {
715
722
return values.canEndLexicalLifetime ();
716
723
}
717
724
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
+
718
746
// / Begin a lexical borrow scope for the value stored into the provided
719
747
// / StoreInst after that instruction.
720
748
// /
@@ -1233,27 +1261,9 @@ StackAllocationPromoter::getLiveOutValues(BlockSetVector &phiBlocks,
1233
1261
BlockToInstMap::iterator it = initializationPoints.find (domBlock);
1234
1262
if (it != initializationPoints.end ()) {
1235
1263
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);
1257
1267
}
1258
1268
1259
1269
// If there is a Phi definition in this block:
@@ -1806,8 +1816,13 @@ void StackAllocationPromoter::run() {
1806
1816
if (asi->getType ().isOrHasEnum ()) {
1807
1817
for (auto it : initializationPoints) {
1808
1818
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
+ }
1811
1826
}
1812
1827
}
1813
1828
@@ -1817,8 +1832,12 @@ void StackAllocationPromoter::run() {
1817
1832
// Now, complete lifetimes!
1818
1833
OSSALifetimeCompletion completion (function, domInfo);
1819
1834
1835
+ // We may have incomplete lifetimes for enum locations on trivial paths.
1836
+ // After promoting them, complete lifetime here.
1820
1837
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 );
1822
1841
}
1823
1842
}
1824
1843
@@ -2119,33 +2138,6 @@ bool MemoryToRegisters::promoteSingleAllocation(AllocStackInst *alloc) {
2119
2138
<< *alloc);
2120
2139
deleter.forceDeleteWithUsers (alloc);
2121
2140
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 ;
2149
2141
}
2150
2142
2151
2143
LLVM_DEBUG (llvm::dbgs () << " *** Need to insert BB arguments for " << *alloc);
0 commit comments