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"
@@ -742,13 +743,12 @@ TempRValueOptPass::tryOptimizeStoreIntoTemp(StoreInst *si) {
742
743
if (user == si)
743
744
continue ;
744
745
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)) {
752
752
return std::next (si->getIterator ());
753
753
}
754
754
@@ -864,6 +864,7 @@ TempRValueOptPass::tryOptimizeStoreIntoTemp(StoreInst *si) {
864
864
si->eraseFromParent ();
865
865
tempObj->eraseFromParent ();
866
866
invalidateAnalysis (SILAnalysis::InvalidationKind::Instructions);
867
+
867
868
return nextIter;
868
869
}
869
870
@@ -873,12 +874,19 @@ TempRValueOptPass::tryOptimizeStoreIntoTemp(StoreInst *si) {
873
874
874
875
// / The main entry point of the pass.
875
876
void 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;
878
885
879
886
// Find all copy_addr instructions.
880
887
llvm::SmallSetVector<CopyAddrInst *, 8 > deadCopies;
881
- for (auto &block : *getFunction ()) {
888
+
889
+ for (auto &block : *function) {
882
890
// Increment the instruction iterator only after calling
883
891
// tryOptimizeCopyIntoTemp because the instruction after CopyInst might be
884
892
// deleted, but copyInst itself won't be deleted until later.
@@ -899,7 +907,21 @@ void TempRValueOptPass::run() {
899
907
}
900
908
901
909
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
+
902
914
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
+ }
903
925
continue ;
904
926
}
905
927
@@ -916,7 +938,7 @@ void TempRValueOptPass::run() {
916
938
}
917
939
);
918
940
919
- DeadEndBlocks deBlocks (getFunction () );
941
+ DeadEndBlocks deBlocks (function );
920
942
for (auto *deadCopy : deadCopies) {
921
943
auto *srcInst = deadCopy->getSrc ()->getDefiningInstruction ();
922
944
deadCopy->eraseFromParent ();
@@ -929,6 +951,12 @@ void TempRValueOptPass::run() {
929
951
if (!deadCopies.empty ()) {
930
952
invalidateAnalysis (SILAnalysis::InvalidationKind::Instructions);
931
953
}
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
+ }
932
960
}
933
961
934
962
SILTransform *swift::createTempRValueOpt () { return new TempRValueOptPass (); }
0 commit comments