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"
@@ -742,13 +743,12 @@ TempRValueOptPass::tryOptimizeStoreIntoTemp(StoreInst *si) {
742743 if (user == si)
743744 continue ;
744745
745- // For enums we require that all uses are in the same block.
746- // Otherwise it could be a switch_enum of an optional where the none-case
747- // does not have a destroy of the enum value.
748- // After transforming such an alloc_stack the value would leak in the none-
749- // case block.
750- if (isOrHasEnum && user->getParent () != si->getParent () &&
751- !isa<DeallocStackInst>(user)) {
746+ // For lexical stored values that are enums, we require that all uses are in
747+ // the same block. This is because we can have incomplete address lifetimes
748+ // on none/trivial paths. and OSSALifetimeCompletion currently can complete
749+ // lexical values only in the presence of dead end blocks.
750+ if (isOrHasEnum && si->getSrc ()->isLexical () &&
751+ user->getParent () != si->getParent () && !isa<DeallocStackInst>(user)) {
752752 return std::next (si->getIterator ());
753753 }
754754
@@ -864,6 +864,7 @@ TempRValueOptPass::tryOptimizeStoreIntoTemp(StoreInst *si) {
864864 si->eraseFromParent ();
865865 tempObj->eraseFromParent ();
866866 invalidateAnalysis (SILAnalysis::InvalidationKind::Instructions);
867+
867868 return nextIter;
868869}
869870
@@ -873,12 +874,19 @@ TempRValueOptPass::tryOptimizeStoreIntoTemp(StoreInst *si) {
873874
874875// / The main entry point of the pass.
875876void TempRValueOptPass::run () {
876- LLVM_DEBUG (llvm::dbgs () << " Copy Peephole in Func "
877- << getFunction ()->getName () << " \n " );
877+ auto *function = getFunction ();
878+
879+ auto *da = PM->getAnalysis <DominanceAnalysis>();
880+
881+ LLVM_DEBUG (llvm::dbgs () << " Copy Peephole in Func " << function->getName ()
882+ << " \n " );
883+
884+ SmallVector<SILValue> valuesToComplete;
878885
879886 // Find all copy_addr instructions.
880887 llvm::SmallSetVector<CopyAddrInst *, 8 > deadCopies;
881- for (auto &block : *getFunction ()) {
888+
889+ for (auto &block : *function) {
882890 // Increment the instruction iterator only after calling
883891 // tryOptimizeCopyIntoTemp because the instruction after CopyInst might be
884892 // deleted, but copyInst itself won't be deleted until later.
@@ -899,7 +907,21 @@ void TempRValueOptPass::run() {
899907 }
900908
901909 if (auto *si = dyn_cast<StoreInst>(&*ii)) {
910+ auto stored = si->getSrc ();
911+ bool isOrHasEnum = stored->getType ().isOrHasEnum ();
912+ auto nextIter = std::next (si->getIterator ());
913+
902914 ii = tryOptimizeStoreIntoTemp (si);
915+
916+ // If the optimization was successful, and the stack loc was an enum
917+ // type, collect the stored value for lifetime completion.
918+ // This is needed because we can have incomplete address lifetimes on
919+ // none/trivial paths for an enum type. Once we convert to value form,
920+ // this will cause incomplete value lifetimes which can raise ownership
921+ // verification errors, because we rely on linear lifetimes in OSSA.
922+ if (ii == nextIter && isOrHasEnum) {
923+ valuesToComplete.push_back (stored);
924+ }
903925 continue ;
904926 }
905927
@@ -916,7 +938,7 @@ void TempRValueOptPass::run() {
916938 }
917939 );
918940
919- DeadEndBlocks deBlocks (getFunction () );
941+ DeadEndBlocks deBlocks (function );
920942 for (auto *deadCopy : deadCopies) {
921943 auto *srcInst = deadCopy->getSrc ()->getDefiningInstruction ();
922944 deadCopy->eraseFromParent ();
@@ -929,6 +951,12 @@ void TempRValueOptPass::run() {
929951 if (!deadCopies.empty ()) {
930952 invalidateAnalysis (SILAnalysis::InvalidationKind::Instructions);
931953 }
954+
955+ // Call the utlity to complete ossa lifetime.
956+ OSSALifetimeCompletion completion (function, da->get (function));
957+ for (auto it : valuesToComplete) {
958+ completion.completeOSSALifetime (it);
959+ }
932960}
933961
934962SILTransform *swift::createTempRValueOpt () { return new TempRValueOptPass (); }
0 commit comments