22
22
#include " swift/SIL/DebugUtils.h"
23
23
#include " swift/SIL/MemAccessUtils.h"
24
24
#include " swift/SIL/NodeBits.h"
25
+ #include " swift/SIL/OSSALifetimeCompletion.h"
25
26
#include " swift/SIL/OwnershipUtils.h"
26
27
#include " swift/SIL/SILArgument.h"
27
28
#include " swift/SIL/SILBuilder.h"
@@ -704,13 +705,12 @@ TempRValueOptPass::tryOptimizeStoreIntoTemp(StoreInst *si) {
704
705
if (user == si)
705
706
continue ;
706
707
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)) {
714
714
return std::next (si->getIterator ());
715
715
}
716
716
@@ -826,6 +826,7 @@ TempRValueOptPass::tryOptimizeStoreIntoTemp(StoreInst *si) {
826
826
si->eraseFromParent ();
827
827
tempObj->eraseFromParent ();
828
828
invalidateAnalysis (SILAnalysis::InvalidationKind::Instructions);
829
+
829
830
return nextIter;
830
831
}
831
832
@@ -835,12 +836,19 @@ TempRValueOptPass::tryOptimizeStoreIntoTemp(StoreInst *si) {
835
836
836
837
// / The main entry point of the pass.
837
838
void 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;
840
847
841
848
// Find all copy_addr instructions.
842
849
llvm::SmallSetVector<CopyAddrInst *, 8 > deadCopies;
843
- for (auto &block : *getFunction ()) {
850
+
851
+ for (auto &block : *function) {
844
852
// Increment the instruction iterator only after calling
845
853
// tryOptimizeCopyIntoTemp because the instruction after CopyInst might be
846
854
// deleted, but copyInst itself won't be deleted until later.
@@ -861,7 +869,21 @@ void TempRValueOptPass::run() {
861
869
}
862
870
863
871
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
+
864
876
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
+ }
865
887
continue ;
866
888
}
867
889
@@ -878,7 +900,7 @@ void TempRValueOptPass::run() {
878
900
}
879
901
);
880
902
881
- DeadEndBlocks deBlocks (getFunction () );
903
+ DeadEndBlocks deBlocks (function );
882
904
for (auto *deadCopy : deadCopies) {
883
905
auto *srcInst = deadCopy->getSrc ()->getDefiningInstruction ();
884
906
deadCopy->eraseFromParent ();
@@ -891,6 +913,12 @@ void TempRValueOptPass::run() {
891
913
if (!deadCopies.empty ()) {
892
914
invalidateAnalysis (SILAnalysis::InvalidationKind::Instructions);
893
915
}
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
+ }
894
922
}
895
923
896
924
SILTransform *swift::createTempRValueOpt () { return new TempRValueOptPass (); }
0 commit comments