2222#include " swift/SIL/DebugUtils.h"
2323#include " swift/SIL/MemAccessUtils.h"
2424#include " swift/SIL/NodeBits.h"
25+ #include " swift/SIL/OSSALifetimeCompletion.h"
2526#include " swift/SIL/OwnershipUtils.h"
2627#include " swift/SIL/SILArgument.h"
2728#include " swift/SIL/SILBuilder.h"
@@ -704,13 +705,12 @@ TempRValueOptPass::tryOptimizeStoreIntoTemp(StoreInst *si) {
704705 if (user == si)
705706 continue ;
706707
707- // For enums we require that all uses are in the same block.
708- // Otherwise it could be a switch_enum of an optional where the none-case
709- // does not have a destroy of the enum value.
710- // After transforming such an alloc_stack the value would leak in the none-
711- // case block.
712- if (isOrHasEnum && user->getParent () != si->getParent () &&
713- !isa<DeallocStackInst>(user)) {
708+ // For lexical stored values that are enums, we require that all uses are in
709+ // the same block. This is because we can have incomplete address lifetimes
710+ // on none/trivial paths. and OSSALifetimeCompletion currently can complete
711+ // lexical values only in the presence of dead end blocks.
712+ if (isOrHasEnum && si->getSrc ()->isLexical () &&
713+ user->getParent () != si->getParent () && !isa<DeallocStackInst>(user)) {
714714 return std::next (si->getIterator ());
715715 }
716716
@@ -826,6 +826,7 @@ TempRValueOptPass::tryOptimizeStoreIntoTemp(StoreInst *si) {
826826 si->eraseFromParent ();
827827 tempObj->eraseFromParent ();
828828 invalidateAnalysis (SILAnalysis::InvalidationKind::Instructions);
829+
829830 return nextIter;
830831}
831832
@@ -835,12 +836,19 @@ TempRValueOptPass::tryOptimizeStoreIntoTemp(StoreInst *si) {
835836
836837// / The main entry point of the pass.
837838void TempRValueOptPass::run () {
838- LLVM_DEBUG (llvm::dbgs () << " Copy Peephole in Func "
839- << getFunction ()->getName () << " \n " );
839+ auto *function = getFunction ();
840+
841+ auto *da = PM->getAnalysis <DominanceAnalysis>();
842+
843+ LLVM_DEBUG (llvm::dbgs () << " Copy Peephole in Func " << function->getName ()
844+ << " \n " );
845+
846+ SmallVector<SILValue> valuesToComplete;
840847
841848 // Find all copy_addr instructions.
842849 llvm::SmallSetVector<CopyAddrInst *, 8 > deadCopies;
843- for (auto &block : *getFunction ()) {
850+
851+ for (auto &block : *function) {
844852 // Increment the instruction iterator only after calling
845853 // tryOptimizeCopyIntoTemp because the instruction after CopyInst might be
846854 // deleted, but copyInst itself won't be deleted until later.
@@ -861,7 +869,21 @@ void TempRValueOptPass::run() {
861869 }
862870
863871 if (auto *si = dyn_cast<StoreInst>(&*ii)) {
872+ auto stored = si->getSrc ();
873+ bool isOrHasEnum = stored->getType ().isOrHasEnum ();
874+ auto nextIter = std::next (si->getIterator ());
875+
864876 ii = tryOptimizeStoreIntoTemp (si);
877+
878+ // If the optimization was successful, and the stack loc was an enum
879+ // type, collect the stored value for lifetime completion.
880+ // This is needed because we can have incomplete address lifetimes on
881+ // none/trivial paths for an enum type. Once we convert to value form,
882+ // this will cause incomplete value lifetimes which can raise ownership
883+ // verification errors, because we rely on linear lifetimes in OSSA.
884+ if (ii == nextIter && isOrHasEnum) {
885+ valuesToComplete.push_back (stored);
886+ }
865887 continue ;
866888 }
867889
@@ -878,7 +900,7 @@ void TempRValueOptPass::run() {
878900 }
879901 );
880902
881- DeadEndBlocks deBlocks (getFunction () );
903+ DeadEndBlocks deBlocks (function );
882904 for (auto *deadCopy : deadCopies) {
883905 auto *srcInst = deadCopy->getSrc ()->getDefiningInstruction ();
884906 deadCopy->eraseFromParent ();
@@ -891,6 +913,12 @@ void TempRValueOptPass::run() {
891913 if (!deadCopies.empty ()) {
892914 invalidateAnalysis (SILAnalysis::InvalidationKind::Instructions);
893915 }
916+
917+ // Call the utlity to complete ossa lifetime.
918+ OSSALifetimeCompletion completion (function, da->get (function));
919+ for (auto it : valuesToComplete) {
920+ completion.completeOSSALifetime (it);
921+ }
894922}
895923
896924SILTransform *swift::createTempRValueOpt () { return new TempRValueOptPass (); }
0 commit comments