SILGenFunction::SILGenFunction(SILGenModule &SGM, SILFunction &F) : SGM(SGM), F(F), silConv(SGM.M), StartOfPostmatter(F.end()), B(*this, createBasicBlock()), OpenedArchetypesTracker(F), CurrentSILLoc(F.getLocation()), Cleanups(*this) { B.setCurrentDebugScope(F.getDebugScope()); B.setOpenedArchetypesTracker(&OpenedArchetypesTracker); }
SILGenFunction::SILGenFunction(SILGenModule &SGM, SILFunction &F, DeclContext *DC) : SGM(SGM), F(F), silConv(SGM.M), FunctionDC(DC), StartOfPostmatter(F.end()), B(*this), OpenedArchetypesTracker(&F), CurrentSILLoc(F.getLocation()), Cleanups(*this), StatsTracer(SGM.M.getASTContext().Stats, "SILGen-function", &F) { assert(DC && "creating SGF without a DeclContext?"); B.setInsertionPoint(createBasicBlock()); B.setCurrentDebugScope(F.getDebugScope()); B.setOpenedArchetypesTracker(&OpenedArchetypesTracker); }
static bool processFunction(SILFunction &Fn) { bool Changed = false; for (auto BI = Fn.begin(), BE = Fn.end(); BI != BE; ++BI) { auto II = BI->begin(), IE = BI->end(); while (II != IE) { SILInstruction *Inst = &*II; DEBUG(llvm::dbgs() << "Visiting: " << *Inst); if (auto *CA = dyn_cast<CopyAddrInst>(Inst)) if (expandCopyAddr(CA)) { ++II; CA->eraseFromParent(); Changed = true; continue; } if (auto *DA = dyn_cast<DestroyAddrInst>(Inst)) if (expandDestroyAddr(DA)) { ++II; DA->eraseFromParent(); Changed = true; continue; } if (auto *CV = dyn_cast<RetainValueInst>(Inst)) if (expandRetainValue(CV)) { ++II; CV->eraseFromParent(); Changed = true; continue; } if (auto *DV = dyn_cast<ReleaseValueInst>(Inst)) if (expandReleaseValue(DV)) { ++II; DV->eraseFromParent(); Changed = true; continue; } ++II; } } return Changed; }
static bool removeUnreachableBlocks(SILFunction &F, SILModule &M, UnreachableUserCodeReportingState *State) { if (F.empty()) return false; SILBasicBlockSet Reachable; SmallVector<SILBasicBlock*, 128> Worklist; Worklist.push_back(&F.front()); Reachable.insert(&F.front()); // Collect all reachable blocks by walking the successors. do { SILBasicBlock *BB = Worklist.pop_back_val(); for (auto SI = BB->succ_begin(), SE = BB->succ_end(); SI != SE; ++SI) { if (Reachable.insert(*SI).second) Worklist.push_back(*SI); } } while (!Worklist.empty()); assert(Reachable.size() <= F.size()); // If everything is reachable, we are done. if (Reachable.size() == F.size()) return false; // Diagnose user written unreachable code. if (State) { for (auto BI = State->PossiblyUnreachableBlocks.begin(), BE = State->PossiblyUnreachableBlocks.end(); BI != BE; ++BI) { const SILBasicBlock *BB = *BI; if (!Reachable.count(BB)) { llvm::SmallPtrSet<const SILBasicBlock *, 1> visited; diagnoseUnreachableBlock(**BI, M, Reachable, State, BB, visited); } } } // Remove references from the dead blocks. for (auto I = F.begin(), E = F.end(); I != E; ++I) { SILBasicBlock *BB = &*I; if (Reachable.count(BB)) continue; // Drop references to other blocks. recursivelyDeleteTriviallyDeadInstructions(BB->getTerminator(), true); NumInstructionsRemoved++; } // Delete dead instructions and everything that could become dead after // their deletion. llvm::SmallVector<SILInstruction*, 32> ToBeDeleted; for (auto BI = F.begin(), BE = F.end(); BI != BE; ++BI) if (!Reachable.count(&*BI)) for (auto I = BI->begin(), E = BI->end(); I != E; ++I) ToBeDeleted.push_back(&*I); recursivelyDeleteTriviallyDeadInstructions(ToBeDeleted, true); NumInstructionsRemoved += ToBeDeleted.size(); // Delete the dead blocks. for (auto I = F.begin(), E = F.end(); I != E;) if (!Reachable.count(&*I)) { I = F.getBlocks().erase(I); NumBlocksRemoved++; } else ++I; return true; }