@@ -754,6 +754,7 @@ void SSADestroyHoisting::run() {
754
754
llvm::SmallVector<AllocStackInst *, 4 > asis;
755
755
llvm::SmallVector<BeginAccessInst *, 4 > bais;
756
756
llvm::SmallVector<StoreInst *, 4 > sis;
757
+ llvm::SmallVector<CopyAddrInst *, 4 > cais;
757
758
758
759
// Collect the instructions that we'll be transforming.
759
760
for (auto &block : *getFunction ()) {
@@ -768,6 +769,10 @@ void SSADestroyHoisting::run() {
768
769
if (si->getOwnershipQualifier () == StoreOwnershipQualifier::Assign) {
769
770
sis.push_back (si);
770
771
}
772
+ } else if (auto *cai = dyn_cast<CopyAddrInst>(&inst)) {
773
+ if (cai->isInitializationOfDest () == IsNotInitialization) {
774
+ cais.push_back (cai);
775
+ }
771
776
}
772
777
}
773
778
}
@@ -804,6 +809,32 @@ void SSADestroyHoisting::run() {
804
809
remainingDestroyAddrs.insert (dai);
805
810
++splitDestroys;
806
811
}
812
+ // Similarly, also expand each
813
+ //
814
+ // copy_addr to
815
+ //
816
+ // instruction into
817
+ //
818
+ // destroy_addr
819
+ // copy_addr to [initialization]
820
+ //
821
+ // sequences to create still more destroy_addrs to hoist.
822
+ //
823
+ // As above, record the newly created destroy_addrs and copy_addrs off of
824
+ // which they were split. After hoisting, we'll merge them back together when
825
+ // possible.
826
+ llvm::SmallVector<std::pair<DestroyAddrInst *, CopyAddrInst *>, 8 >
827
+ splitDestroysAndCopies;
828
+ for (auto *cai : cais) {
829
+ auto builder = SILBuilderWithScope (cai);
830
+ auto *dai = builder.createDestroyAddr (
831
+ RegularLocation::getAutoGeneratedLocation (cai->getLoc ()),
832
+ cai->getOperand (1 ));
833
+ cai->setIsInitializationOfDest (IsInitialization);
834
+ splitDestroysAndCopies.push_back ({dai, cai});
835
+ remainingDestroyAddrs.insert (dai);
836
+ ++splitDestroys;
837
+ }
807
838
808
839
// We assume that the function is in reverse post order so visiting the
809
840
// blocks and pushing begin_access as we see them and then popping them off
@@ -840,17 +871,29 @@ void SSADestroyHoisting::run() {
840
871
if (!remainingDestroyAddrs.contains (dai))
841
872
continue ;
842
873
auto *si = pair.second ;
843
- if (dai->getNextInstruction () == si) {
844
- // No stores should have been rewritten during hoisting. Their ownership
845
- // qualifiers were set to [init] when splitting off the destroy_addrs.
846
- assert (si->getOwnershipQualifier () == StoreOwnershipQualifier::Init);
847
- // If a newly created destroy_addr has not been hoisted from its previous
848
- // location, combine it back together with the store [init] which it was
849
- // split off from.
850
- deleter.forceDelete (dai);
851
- si->setOwnershipQualifier (StoreOwnershipQualifier::Assign);
852
- --splitDestroys;
853
- }
874
+ if (dai->getNextInstruction () != si)
875
+ continue ;
876
+ // No stores should have been rewritten during hoisting. Their ownership
877
+ // qualifiers were set to [init] when splitting off the destroy_addrs.
878
+ assert (si->getOwnershipQualifier () == StoreOwnershipQualifier::Init);
879
+ // If a newly created destroy_addr has not been hoisted from its previous
880
+ // location, combine it back together with the store [init] which it was
881
+ // split off from.
882
+ deleter.forceDelete (dai);
883
+ si->setOwnershipQualifier (StoreOwnershipQualifier::Assign);
884
+ --splitDestroys;
885
+ }
886
+ for (auto pair : splitDestroysAndCopies) {
887
+ auto *dai = pair.first ;
888
+ if (!remainingDestroyAddrs.contains (dai))
889
+ continue ;
890
+ auto *cai = pair.second ;
891
+ if (dai->getNextInstruction () != cai)
892
+ continue ;
893
+ assert (cai->isInitializationOfDest () == IsInitialization);
894
+ deleter.forceDelete (dai);
895
+ cai->setIsInitializationOfDest (IsNotInitialization);
896
+ --splitDestroys;
854
897
}
855
898
// If there were any destroy_addrs split off of stores and not recombined
856
899
// with them, then the function has changed.
0 commit comments