@@ -123,8 +123,7 @@ class LiveValues {
123123 }
124124
125125 void endLexicalLifetimeBeforeInst (AllocStackInst *asi,
126- SILInstruction *beforeInstruction,
127- SILBuilderContext &ctx);
126+ SILInstruction *beforeInstruction);
128127 };
129128 struct Guaranteed {
130129 SILValue stored = SILValue();
@@ -173,8 +172,7 @@ class LiveValues {
173172 }
174173
175174 void endLexicalLifetimeBeforeInst (AllocStackInst *asi,
176- SILInstruction *beforeInstruction,
177- SILBuilderContext &ctx);
175+ SILInstruction *beforeInstruction);
178176 };
179177 struct None {
180178 SILValue stored = SILValue();
@@ -190,8 +188,7 @@ class LiveValues {
190188 bool canEndLexicalLifetime () { return false ; }
191189
192190 void endLexicalLifetimeBeforeInst (AllocStackInst *asi,
193- SILInstruction *beforeInstruction,
194- SILBuilderContext &ctx);
191+ SILInstruction *beforeInstruction);
195192 };
196193
197194private:
@@ -289,23 +286,22 @@ class LiveValues {
289286 }
290287
291288 void endLexicalLifetimeBeforeInst (AllocStackInst *asi,
292- SILInstruction *beforeInstruction,
293- SILBuilderContext &ctx) {
289+ SILInstruction *beforeInstruction) {
294290 if (auto *owned = storage.dyn_cast <Owned>()) {
295- return owned->endLexicalLifetimeBeforeInst (asi, beforeInstruction, ctx );
291+ return owned->endLexicalLifetimeBeforeInst (asi, beforeInstruction);
296292 } else if (auto *none = storage.dyn_cast <None>()) {
297- return none->endLexicalLifetimeBeforeInst (asi, beforeInstruction, ctx );
293+ return none->endLexicalLifetimeBeforeInst (asi, beforeInstruction);
298294 }
299295 auto &guaranteed = storage.get <Guaranteed>();
300- return guaranteed.endLexicalLifetimeBeforeInst (asi, beforeInstruction, ctx );
296+ return guaranteed.endLexicalLifetimeBeforeInst (asi, beforeInstruction);
301297 }
302298
303299 bool endLexicalLifetimeBeforeInstIfPossible (AllocStackInst *asi,
304300 SILInstruction *beforeInstruction,
305301 SILBuilderContext &ctx) {
306302 if (!canEndLexicalLifetime ())
307303 return false ;
308- endLexicalLifetimeBeforeInst (asi, beforeInstruction, ctx );
304+ endLexicalLifetimeBeforeInst (asi, beforeInstruction);
309305 return true ;
310306 }
311307};
@@ -392,6 +388,17 @@ static bool isLoadFromStack(SILInstruction *i, AllocStackInst *asi) {
392388 return true ;
393389}
394390
391+ // / Whether the storage is invalid after \p i.
392+ // /
393+ // / This is exactly when the instruction is a load [take].
394+ static bool doesLoadInvalidateStorage (SILInstruction *i) {
395+ auto *li = dyn_cast<LoadInst>(i);
396+ if (!li) {
397+ return false ;
398+ }
399+ return li->getOwnershipQualifier () == LoadOwnershipQualifier::Take;
400+ }
401+
395402// / Collects all load instructions which (transitively) use \p i as address.
396403static void collectLoads (SILInstruction *i,
397404 SmallVectorImpl<SILInstruction *> &foundLoads) {
@@ -811,17 +818,15 @@ beginGuaranteedLexicalLifetimeAfterStore(AllocStackInst *asi,
811818// / it will already have been ended naturally by destroy_addrs (or equivalent)
812819// / of the alloc_stack.
813820void LiveValues::Owned::endLexicalLifetimeBeforeInst (
814- AllocStackInst *asi, SILInstruction *beforeInstruction,
815- SILBuilderContext &ctx) {
821+ AllocStackInst *asi, SILInstruction *beforeInstruction) {
816822 assert (lexicalLifetimeEnsured (asi));
817823 assert (beforeInstruction);
818824}
819825
820826// / End the lexical borrow scope for an @guaranteed stored value described by
821827// / the provided LiveValues struct before the specified instruction.
822828void LiveValues::Guaranteed::endLexicalLifetimeBeforeInst (
823- AllocStackInst *asi, SILInstruction *beforeInstruction,
824- SILBuilderContext &ctx) {
829+ AllocStackInst *asi, SILInstruction *beforeInstruction) {
825830 assert (lexicalLifetimeEnsured (asi));
826831 assert (beforeInstruction);
827832 assert (borrow);
@@ -831,8 +836,7 @@ void LiveValues::Guaranteed::endLexicalLifetimeBeforeInst(
831836}
832837
833838void LiveValues::None::endLexicalLifetimeBeforeInst (
834- AllocStackInst *asi, SILInstruction *beforeInstruction,
835- SILBuilderContext &ctx) {
839+ AllocStackInst *asi, SILInstruction *beforeInstruction) {
836840 llvm::report_fatal_error (
837841 " can't have lexical lifetime for ownership none value" );
838842}
@@ -1061,7 +1065,7 @@ SILInstruction *StackAllocationPromoter::promoteAllocationInBlock(
10611065 if (runningVals && runningVals->value .canEndLexicalLifetime ()) {
10621066 // End it right now if we have enough information.
10631067 runningVals->value .getOwned ().endLexicalLifetimeBeforeInst (
1064- asi, /* beforeInstruction=*/ li, ctx );
1068+ asi, /* beforeInstruction=*/ li);
10651069 } else {
10661070 // If we don't have enough information, end it endLexicalLifetime.
10671071 assert (!deinitializationPoints[blockPromotingWithin]);
@@ -1088,7 +1092,7 @@ SILInstruction *StackAllocationPromoter::promoteAllocationInBlock(
10881092 // StackAllocationPromoter::fixBranchesAndUses will later handle it.
10891093 LLVM_DEBUG (llvm::dbgs () << " *** First load: " << *li);
10901094 runningVals = {LiveValues::toReplace (asi, /* replacement=*/ li),
1091- /* isStorageValid=*/ true };
1095+ /* isStorageValid=*/ ! doesLoadInvalidateStorage (inst) };
10921096 }
10931097 continue ;
10941098 }
@@ -1143,7 +1147,7 @@ SILInstruction *StackAllocationPromoter::promoteAllocationInBlock(
11431147 if (oldRunningVals && oldRunningVals->isStorageValid &&
11441148 oldRunningVals->value .canEndLexicalLifetime ()) {
11451149 oldRunningVals->value .getOwned ().endLexicalLifetimeBeforeInst (
1146- asi, /* beforeInstruction=*/ si, ctx );
1150+ asi, /* beforeInstruction=*/ si);
11471151 }
11481152 runningVals = beginOwnedLexicalLifetimeAfterStore (asi, si);
11491153 }
@@ -1175,9 +1179,6 @@ SILInstruction *StackAllocationPromoter::promoteAllocationInBlock(
11751179
11761180 // End the lexical lifetime of the store_borrow source.
11771181 if (auto *ebi = dyn_cast<EndBorrowInst>(inst)) {
1178- if (!lexicalLifetimeEnsured (asi, lastStoreInst)) {
1179- continue ;
1180- }
11811182 auto *sbi = dyn_cast<StoreBorrowInst>(ebi->getOperand ());
11821183 if (!sbi) {
11831184 continue ;
@@ -1196,8 +1197,10 @@ SILInstruction *StackAllocationPromoter::promoteAllocationInBlock(
11961197 if (sbi->getSrc () != runningVals->value .getStored ()) {
11971198 continue ;
11981199 }
1199- // Mark storage as invalid and mark end_borrow as a deinit point.
12001200 runningVals->isStorageValid = false ;
1201+ if (!lexicalLifetimeEnsured (asi, lastStoreInst)) {
1202+ continue ;
1203+ }
12011204 runningVals->value .endLexicalLifetimeBeforeInstIfPossible (
12021205 asi, ebi->getNextInstruction (), ctx);
12031206 continue ;
@@ -1214,6 +1217,7 @@ SILInstruction *StackAllocationPromoter::promoteAllocationInBlock(
12141217 continue ;
12151218 }
12161219 if (runningVals) {
1220+ assert (runningVals->isStorageValid );
12171221 replaceDestroy (dai, runningVals->value .replacement (asi, dai), ctx,
12181222 deleter, instructionsToDelete);
12191223 if (lexicalLifetimeEnsured (asi, lastStoreInst)) {
@@ -1968,9 +1972,8 @@ void MemoryToRegisters::removeSingleBlockAllocation(AllocStackInst *asi) {
19681972 LiveValues::toReplace (asi,
19691973 /* replacement=*/ createEmptyAndUndefValue (
19701974 asi->getElementType (), inst, ctx)),
1971- /* isStorageValid=*/ true };
1975+ /* isStorageValid=*/ ! doesLoadInvalidateStorage (inst) };
19721976 }
1973- assert (runningVals && runningVals->isStorageValid );
19741977 auto *loadInst = dyn_cast<LoadInst>(inst);
19751978 if (loadInst &&
19761979 loadInst->getOwnershipQualifier () == LoadOwnershipQualifier::Take) {
@@ -2039,13 +2042,13 @@ void MemoryToRegisters::removeSingleBlockAllocation(AllocStackInst *asi) {
20392042 if (!runningVals.has_value ()) {
20402043 continue ;
20412044 }
2042- if (!runningVals->value .isGuaranteed ()) {
2043- continue ;
2044- }
20452045 if (sbi->getSrc () != runningVals->value .getStored ()) {
20462046 continue ;
20472047 }
20482048 runningVals->isStorageValid = false ;
2049+ if (!runningVals->value .isGuaranteed ()) {
2050+ continue ;
2051+ }
20492052 runningVals->value .endLexicalLifetimeBeforeInstIfPossible (
20502053 asi, ebi->getNextInstruction (), ctx);
20512054 continue ;
@@ -2094,24 +2097,32 @@ void MemoryToRegisters::removeSingleBlockAllocation(AllocStackInst *asi) {
20942097 }
20952098 }
20962099
2097- if (lexicalLifetimeEnsured (asi) && runningVals &&
2098- runningVals->isStorageValid &&
2099- runningVals->value .getStored ()->getOwnershipKind ().isCompatibleWith (
2100- OwnershipKind::Owned)) {
2101- // There is still valid storage after visiting all instructions in this
2102- // block which are the only instructions involving this alloc_stack.
2103- // This can only happen if all paths from this block end in unreachable.
2104- //
2105- // We need to end the lexical lifetime at the last possible location, at the
2106- // boundary blocks which are the predecessors of dominance frontier
2107- // dominated by the alloc_stack.
2108- SmallVector<SILBasicBlock *, 4 > boundary;
2109- computeDominatedBoundaryBlocks (asi->getParent (), domInfo, boundary);
2110- for (auto *block : boundary) {
2111- auto *terminator = block->getTerminator ();
2112- runningVals->value .endLexicalLifetimeBeforeInstIfPossible (
2113- asi, /* beforeInstruction=*/ terminator, ctx);
2114- }
2100+ auto *function = asi->getFunction ();
2101+ if (!function->hasOwnership () || !runningVals ||
2102+ !runningVals->isStorageValid ||
2103+ asi->getElementType ().isTrivial (function)) {
2104+ return ;
2105+ }
2106+ // There is still valid storage after visiting all instructions in this
2107+ // block which are the only instructions involving this alloc_stack.
2108+ // That can happen if:
2109+ // (1) this block is a dead-end. TODO: OSSACompleteLifetime: Complete such
2110+ // lifetimes.
2111+ // (2) a trivial case of a non-trivial enum was stored to the address
2112+
2113+ auto *deadEndBlocks = deadEndBlocksAnalysis->get (function);
2114+
2115+ if (!deadEndBlocks->isDeadEnd (parentBlock)) {
2116+ // We may have incomplete lifetimes for enum locations on trivial paths.
2117+ // After promoting them, complete lifetime here.
2118+ ASSERT (asi->getElementType ().isOrHasEnum ());
2119+ OSSACompleteLifetime completion (function, domInfo, *deadEndBlocks,
2120+ OSSACompleteLifetime::IgnoreTrivialVariable,
2121+ /* forceLivenessVerification=*/ false ,
2122+ /* nonDestroyingEnd=*/ true );
2123+ completion.completeOSSALifetime (
2124+ runningVals->value .replacement (asi, nullptr ),
2125+ OSSACompleteLifetime::Boundary::Liveness);
21152126 }
21162127}
21172128
@@ -2211,7 +2222,8 @@ bool MemoryToRegisters::promoteAllocation(AllocStackInst *alloc,
22112222 }
22122223
22132224 // Remove write-only AllocStacks.
2214- if (isWriteOnlyAllocation (alloc) && !lexicalLifetimeEnsured (alloc)) {
2225+ if (isWriteOnlyAllocation (alloc) && !alloc->getType ().isOrHasEnum () &&
2226+ !lexicalLifetimeEnsured (alloc)) {
22152227 LLVM_DEBUG (llvm::dbgs () << " *** Deleting store-only AllocStack: " << *alloc);
22162228 deleter.forceDeleteWithUsers (alloc);
22172229 return true ;
0 commit comments