@@ -784,20 +784,35 @@ static bool isAllocatingApply(SILInstruction *Inst) {
784784namespace {
785785class DeadObjectElimination : public SILFunctionTransform {
786786 llvm::DenseMap<SILType, bool > DestructorAnalysisCache;
787- llvm::SmallVector<SILInstruction*, 16 > Allocations;
788787
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 ();
798811 }
799812 }
800813
814+ bool needsNotifications () override { return true ; }
815+
801816 bool processAllocRef (AllocRefInst *ARI);
802817 bool processAllocStack (AllocStackInst *ASI);
803818 bool processKeyPath (KeyPathInst *KPI);
@@ -806,21 +821,30 @@ class DeadObjectElimination : public SILFunctionTransform {
806821
807822 bool processFunction (SILFunction &Fn) {
808823 DeadEndBlocks DEBlocks (&Fn);
809- Allocations.clear ();
810824 DestructorAnalysisCache.clear ();
825+
811826 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+ }
824848 }
825849 return Changed;
826850 }
0 commit comments