@@ -784,20 +784,35 @@ static bool isAllocatingApply(SILInstruction *Inst) {
784
784
namespace {
785
785
class DeadObjectElimination : public SILFunctionTransform {
786
786
llvm::DenseMap<SILType, bool > DestructorAnalysisCache;
787
- llvm::SmallVector<SILInstruction*, 16 > Allocations;
788
787
789
- void collectAllocations (SILFunction &Fn) {
790
- for (auto &BB : Fn) {
791
- for (auto &II : BB) {
792
- if (isa<AllocationInst>(&II) ||
793
- isAllocatingApply (&II) ||
794
- isa<KeyPathInst>(&II)) {
795
- Allocations.push_back (&II);
796
- }
797
- }
788
+ // This is not a SILBasicBlock::iterator because we need a null value and we
789
+ // don't have a specific block whose end() we could use.
790
+ SILInstruction *nextInstToProcess = nullptr ;
791
+
792
+ // / Advance nextInstToProcess to the next instruction in its block.
793
+ // / If nextInstToProcess is the last instruction in its block, it is set to
794
+ // / null.
795
+ void advance () {
796
+ if (!nextInstToProcess)
797
+ return ;
798
+ SILBasicBlock *block = nextInstToProcess->getParent ();
799
+ auto nextIter = std::next (nextInstToProcess->getIterator ());
800
+ if (nextIter == block->end ()) {
801
+ nextInstToProcess = nullptr ;
802
+ } else {
803
+ nextInstToProcess = &*nextIter;
804
+ }
805
+ }
806
+
807
+ void handleDeleteNotification (SILNode *node) override {
808
+ if (auto *inst = dyn_cast<SILInstruction>(node)) {
809
+ if (inst == nextInstToProcess)
810
+ advance ();
798
811
}
799
812
}
800
813
814
+ bool needsNotifications () override { return true ; }
815
+
801
816
bool processAllocRef (AllocRefInst *ARI);
802
817
bool processAllocStack (AllocStackInst *ASI);
803
818
bool processKeyPath (KeyPathInst *KPI);
@@ -806,21 +821,30 @@ class DeadObjectElimination : public SILFunctionTransform {
806
821
807
822
bool processFunction (SILFunction &Fn) {
808
823
DeadEndBlocks DEBlocks (&Fn);
809
- Allocations.clear ();
810
824
DestructorAnalysisCache.clear ();
825
+
811
826
bool Changed = false ;
812
- collectAllocations (Fn);
813
- for (auto *II : Allocations) {
814
- if (auto *A = dyn_cast<AllocRefInst>(II))
815
- Changed |= processAllocRef (A);
816
- else if (auto *A = dyn_cast<AllocStackInst>(II))
817
- Changed |= processAllocStack (A);
818
- else if (auto *KPI = dyn_cast<KeyPathInst>(II))
819
- Changed |= processKeyPath (KPI);
820
- else if (auto *A = dyn_cast<AllocBoxInst>(II))
821
- Changed |= processAllocBox (A);
822
- else if (auto *A = dyn_cast<ApplyInst>(II))
823
- Changed |= processAllocApply (A, DEBlocks);
827
+
828
+ for (auto &BB : Fn) {
829
+ nextInstToProcess = &BB.front ();
830
+
831
+ // We cannot just iterate over the instructions, because the processing
832
+ // functions might deleted instruction before or after the current
833
+ // instruction - and also inst itself.
834
+ while (SILInstruction *inst = nextInstToProcess) {
835
+ advance ();
836
+
837
+ if (auto *A = dyn_cast<AllocRefInst>(inst))
838
+ Changed |= processAllocRef (A);
839
+ else if (auto *A = dyn_cast<AllocStackInst>(inst))
840
+ Changed |= processAllocStack (A);
841
+ else if (auto *KPI = dyn_cast<KeyPathInst>(inst))
842
+ Changed |= processKeyPath (KPI);
843
+ else if (auto *A = dyn_cast<AllocBoxInst>(inst))
844
+ Changed |= processAllocBox (A);
845
+ else if (auto *A = dyn_cast<ApplyInst>(inst))
846
+ Changed |= processAllocApply (A, DEBlocks);
847
+ }
824
848
}
825
849
return Changed;
826
850
}
0 commit comments