diff options
Diffstat (limited to 'llvm/lib/IR/LegacyPassManager.cpp')
-rw-r--r-- | llvm/lib/IR/LegacyPassManager.cpp | 321 |
1 files changed, 211 insertions, 110 deletions
diff --git a/llvm/lib/IR/LegacyPassManager.cpp b/llvm/lib/IR/LegacyPassManager.cpp index 90239bb76298..74869fa62c66 100644 --- a/llvm/lib/IR/LegacyPassManager.cpp +++ b/llvm/lib/IR/LegacyPassManager.cpp @@ -33,7 +33,6 @@ #include <algorithm> #include <unordered_set> using namespace llvm; -using namespace llvm::legacy; // See PassManagers.h for Pass Manager infrastructure overview. @@ -132,7 +131,8 @@ bool llvm::forcePrintModuleIR() { return PrintModuleScope; } bool llvm::isFunctionInPrintList(StringRef FunctionName) { static std::unordered_set<std::string> PrintFuncNames(PrintFuncsList.begin(), PrintFuncsList.end()); - return PrintFuncNames.empty() || PrintFuncNames.count(FunctionName); + return PrintFuncNames.empty() || + PrintFuncNames.count(std::string(FunctionName)); } /// isPassDebuggingExecutionsOrMore - Return true if -debug-pass=Executions /// or higher is specified. @@ -239,7 +239,7 @@ void PMDataManager::emitInstrCountChangedRemark( // Helper lambda that emits a remark when the size of a function has changed. auto EmitFunctionSizeChangedRemark = [&FunctionToInstrCount, &F, &BB, - &PassName](const std::string &Fname) { + &PassName](StringRef Fname) { unsigned FnCountBefore, FnCountAfter; std::pair<unsigned, unsigned> &Change = FunctionToInstrCount[Fname]; std::tie(FnCountBefore, FnCountAfter) = Change; @@ -386,8 +386,68 @@ public: void FunctionPassManagerImpl::anchor() {} char FunctionPassManagerImpl::ID = 0; -} // End of legacy namespace -} // End of llvm namespace + +//===----------------------------------------------------------------------===// +// FunctionPassManagerImpl implementation +// +bool FunctionPassManagerImpl::doInitialization(Module &M) { + bool Changed = false; + + dumpArguments(); + dumpPasses(); + + for (ImmutablePass *ImPass : getImmutablePasses()) + Changed |= ImPass->doInitialization(M); + + for (unsigned Index = 0; Index < getNumContainedManagers(); ++Index) + Changed |= getContainedManager(Index)->doInitialization(M); + + return Changed; +} + +bool FunctionPassManagerImpl::doFinalization(Module &M) { + bool Changed = false; + + for (int Index = getNumContainedManagers() - 1; Index >= 0; --Index) + Changed |= getContainedManager(Index)->doFinalization(M); + + for (ImmutablePass *ImPass : getImmutablePasses()) + Changed |= ImPass->doFinalization(M); + + return Changed; +} + +void FunctionPassManagerImpl::releaseMemoryOnTheFly() { + if (!wasRun) + return; + for (unsigned Index = 0; Index < getNumContainedManagers(); ++Index) { + FPPassManager *FPPM = getContainedManager(Index); + for (unsigned Index = 0; Index < FPPM->getNumContainedPasses(); ++Index) { + FPPM->getContainedPass(Index)->releaseMemory(); + } + } + wasRun = false; +} + +// Execute all the passes managed by this top level manager. +// Return true if any function is modified by a pass. +bool FunctionPassManagerImpl::run(Function &F) { + bool Changed = false; + + initializeAllAnalysisInfo(); + for (unsigned Index = 0; Index < getNumContainedManagers(); ++Index) { + Changed |= getContainedManager(Index)->runOnFunction(F); + F.getContext().yield(); + } + + for (unsigned Index = 0; Index < getNumContainedManagers(); ++Index) + getContainedManager(Index)->cleanup(); + + wasRun = true; + return Changed; +} +} // namespace legacy +} // namespace llvm namespace { //===----------------------------------------------------------------------===// @@ -405,7 +465,7 @@ public: // Delete on the fly managers. ~MPPassManager() override { for (auto &OnTheFlyManager : OnTheFlyManagers) { - FunctionPassManagerImpl *FPP = OnTheFlyManager.second; + legacy::FunctionPassManagerImpl *FPP = OnTheFlyManager.second; delete FPP; } } @@ -436,7 +496,8 @@ public: /// Return function pass corresponding to PassInfo PI, that is /// required by module pass MP. Instantiate analysis pass, by using /// its runOnFunction() for function F. - Pass* getOnTheFlyPass(Pass *MP, AnalysisID PI, Function &F) override; + std::tuple<Pass *, bool> getOnTheFlyPass(Pass *MP, AnalysisID PI, + Function &F) override; StringRef getPassName() const override { return "Module Pass Manager"; } @@ -449,7 +510,7 @@ public: for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) { ModulePass *MP = getContainedPass(Index); MP->dumpPassStructure(Offset + 1); - MapVector<Pass *, FunctionPassManagerImpl *>::const_iterator I = + MapVector<Pass *, legacy::FunctionPassManagerImpl *>::const_iterator I = OnTheFlyManagers.find(MP); if (I != OnTheFlyManagers.end()) I->second->dumpPassStructure(Offset + 2); @@ -469,7 +530,7 @@ public: private: /// Collection of on the fly FPPassManagers. These managers manage /// function passes that are required by module passes. - MapVector<Pass *, FunctionPassManagerImpl *> OnTheFlyManagers; + MapVector<Pass *, legacy::FunctionPassManagerImpl *> OnTheFlyManagers; }; char MPPassManager::ID = 0; @@ -532,8 +593,35 @@ public: void PassManagerImpl::anchor() {} char PassManagerImpl::ID = 0; -} // End of legacy namespace -} // End of llvm namespace + +//===----------------------------------------------------------------------===// +// PassManagerImpl implementation + +// +/// run - Execute all of the passes scheduled for execution. Keep track of +/// whether any of the passes modifies the module, and if so, return true. +bool PassManagerImpl::run(Module &M) { + bool Changed = false; + + dumpArguments(); + dumpPasses(); + + for (ImmutablePass *ImPass : getImmutablePasses()) + Changed |= ImPass->doInitialization(M); + + initializeAllAnalysisInfo(); + for (unsigned Index = 0; Index < getNumContainedManagers(); ++Index) { + Changed |= getContainedManager(Index)->runOnModule(M); + M.getContext().yield(); + } + + for (ImmutablePass *ImPass : getImmutablePasses()) + Changed |= ImPass->doFinalization(M); + + return Changed; +} +} // namespace legacy +} // namespace llvm //===----------------------------------------------------------------------===// // PMTopLevelManager implementation @@ -1289,7 +1377,8 @@ void PMDataManager::addLowerLevelRequiredPass(Pass *P, Pass *RequiredPass) { llvm_unreachable("Unable to schedule pass"); } -Pass *PMDataManager::getOnTheFlyPass(Pass *P, AnalysisID PI, Function &F) { +std::tuple<Pass *, bool> PMDataManager::getOnTheFlyPass(Pass *P, AnalysisID PI, + Function &F) { llvm_unreachable("Unable to find on the fly pass"); } @@ -1306,17 +1395,20 @@ Pass *AnalysisResolver::getAnalysisIfAvailable(AnalysisID ID, bool dir) const { return PM.findAnalysisPass(ID, dir); } -Pass *AnalysisResolver::findImplPass(Pass *P, AnalysisID AnalysisPI, - Function &F) { +std::tuple<Pass *, bool> +AnalysisResolver::findImplPass(Pass *P, AnalysisID AnalysisPI, Function &F) { return PM.getOnTheFlyPass(P, AnalysisPI, F); } +namespace llvm { +namespace legacy { + //===----------------------------------------------------------------------===// // FunctionPassManager implementation /// Create new Function pass manager FunctionPassManager::FunctionPassManager(Module *m) : M(m) { - FPM = new FunctionPassManagerImpl(); + FPM = new legacy::FunctionPassManagerImpl(); // FPM is the top level manager. FPM->setTopLevelManager(FPM); @@ -1355,36 +1447,8 @@ bool FunctionPassManager::doInitialization() { bool FunctionPassManager::doFinalization() { return FPM->doFinalization(*M); } - -//===----------------------------------------------------------------------===// -// FunctionPassManagerImpl implementation -// -bool FunctionPassManagerImpl::doInitialization(Module &M) { - bool Changed = false; - - dumpArguments(); - dumpPasses(); - - for (ImmutablePass *ImPass : getImmutablePasses()) - Changed |= ImPass->doInitialization(M); - - for (unsigned Index = 0; Index < getNumContainedManagers(); ++Index) - Changed |= getContainedManager(Index)->doInitialization(M); - - return Changed; -} - -bool FunctionPassManagerImpl::doFinalization(Module &M) { - bool Changed = false; - - for (int Index = getNumContainedManagers() - 1; Index >= 0; --Index) - Changed |= getContainedManager(Index)->doFinalization(M); - - for (ImmutablePass *ImPass : getImmutablePasses()) - Changed |= ImPass->doFinalization(M); - - return Changed; -} +} // namespace legacy +} // namespace llvm /// cleanup - After running all passes, clean up pass manager cache. void FPPassManager::cleanup() { @@ -1396,35 +1460,6 @@ void FPPassManager::cleanup() { } } -void FunctionPassManagerImpl::releaseMemoryOnTheFly() { - if (!wasRun) - return; - for (unsigned Index = 0; Index < getNumContainedManagers(); ++Index) { - FPPassManager *FPPM = getContainedManager(Index); - for (unsigned Index = 0; Index < FPPM->getNumContainedPasses(); ++Index) { - FPPM->getContainedPass(Index)->releaseMemory(); - } - } - wasRun = false; -} - -// Execute all the passes managed by this top level manager. -// Return true if any function is modified by a pass. -bool FunctionPassManagerImpl::run(Function &F) { - bool Changed = false; - - initializeAllAnalysisInfo(); - for (unsigned Index = 0; Index < getNumContainedManagers(); ++Index) { - Changed |= getContainedManager(Index)->runOnFunction(F); - F.getContext().yield(); - } - - for (unsigned Index = 0; Index < getNumContainedManagers(); ++Index) - getContainedManager(Index)->cleanup(); - - wasRun = true; - return Changed; -} //===----------------------------------------------------------------------===// // FPPassManager implementation @@ -1440,6 +1475,74 @@ void FPPassManager::dumpPassStructure(unsigned Offset) { } } +#ifdef EXPENSIVE_CHECKS +namespace { +namespace details { + +// Basic hashing mechanism to detect structural change to the IR, used to verify +// pass return status consistency with actual change. Loosely copied from +// llvm/lib/Transforms/Utils/FunctionComparator.cpp + +class StructuralHash { + uint64_t Hash = 0x6acaa36bef8325c5ULL; + + void update(uint64_t V) { Hash = hashing::detail::hash_16_bytes(Hash, V); } + +public: + StructuralHash() = default; + + void update(Function &F) { + if (F.empty()) + return; + + update(F.isVarArg()); + update(F.arg_size()); + + SmallVector<const BasicBlock *, 8> BBs; + SmallPtrSet<const BasicBlock *, 16> VisitedBBs; + + BBs.push_back(&F.getEntryBlock()); + VisitedBBs.insert(BBs[0]); + while (!BBs.empty()) { + const BasicBlock *BB = BBs.pop_back_val(); + update(45798); // Block header + for (auto &Inst : *BB) + update(Inst.getOpcode()); + + const Instruction *Term = BB->getTerminator(); + for (unsigned i = 0, e = Term->getNumSuccessors(); i != e; ++i) { + if (!VisitedBBs.insert(Term->getSuccessor(i)).second) + continue; + BBs.push_back(Term->getSuccessor(i)); + } + } + } + + void update(Module &M) { + for (Function &F : M) + update(F); + } + + uint64_t getHash() const { return Hash; } +}; + +} // namespace details + +uint64_t StructuralHash(Function &F) { + details::StructuralHash H; + H.update(F); + return H.getHash(); +} + +uint64_t StructuralHash(Module &M) { + details::StructuralHash H; + H.update(M); + return H.getHash(); +} + +} // end anonymous namespace + +#endif /// Execute all of the passes scheduled for execution by invoking /// runOnFunction method. Keep track of whether any of the passes modifies @@ -1478,7 +1581,16 @@ bool FPPassManager::runOnFunction(Function &F) { { PassManagerPrettyStackEntry X(FP, F); TimeRegion PassTimer(getPassTimer(FP)); +#ifdef EXPENSIVE_CHECKS + uint64_t RefHash = StructuralHash(F); +#endif LocalChanged |= FP->runOnFunction(F); + +#ifdef EXPENSIVE_CHECKS + assert((LocalChanged || (RefHash == StructuralHash(F))) && + "Pass modifies its input and doesn't report it."); +#endif + if (EmitICRemark) { unsigned NewSize = F.getInstructionCount(); @@ -1551,7 +1663,7 @@ MPPassManager::runOnModule(Module &M) { // Initialize on-the-fly passes for (auto &OnTheFlyManager : OnTheFlyManagers) { - FunctionPassManagerImpl *FPP = OnTheFlyManager.second; + legacy::FunctionPassManagerImpl *FPP = OnTheFlyManager.second; Changed |= FPP->doInitialization(M); } @@ -1579,7 +1691,17 @@ MPPassManager::runOnModule(Module &M) { PassManagerPrettyStackEntry X(MP, M); TimeRegion PassTimer(getPassTimer(MP)); +#ifdef EXPENSIVE_CHECKS + uint64_t RefHash = StructuralHash(M); +#endif + LocalChanged |= MP->runOnModule(M); + +#ifdef EXPENSIVE_CHECKS + assert((LocalChanged || (RefHash == StructuralHash(M))) && + "Pass modifies its input and doesn't report it."); +#endif + if (EmitICRemark) { // Update the size of the module. unsigned ModuleCount = M.getInstructionCount(); @@ -1612,7 +1734,7 @@ MPPassManager::runOnModule(Module &M) { // Finalize on-the-fly passes for (auto &OnTheFlyManager : OnTheFlyManagers) { - FunctionPassManagerImpl *FPP = OnTheFlyManager.second; + legacy::FunctionPassManagerImpl *FPP = OnTheFlyManager.second; // We don't know when is the last time an on-the-fly pass is run, // so we need to releaseMemory / finalize here FPP->releaseMemoryOnTheFly(); @@ -1633,9 +1755,9 @@ void MPPassManager::addLowerLevelRequiredPass(Pass *P, Pass *RequiredPass) { RequiredPass->getPotentialPassManagerType()) && "Unable to handle Pass that requires lower level Analysis pass"); - FunctionPassManagerImpl *FPP = OnTheFlyManagers[P]; + legacy::FunctionPassManagerImpl *FPP = OnTheFlyManagers[P]; if (!FPP) { - FPP = new FunctionPassManagerImpl(); + FPP = new legacy::FunctionPassManagerImpl(); // FPP is the top level manager. FPP->setTopLevelManager(FPP); @@ -1664,42 +1786,19 @@ void MPPassManager::addLowerLevelRequiredPass(Pass *P, Pass *RequiredPass) { /// Return function pass corresponding to PassInfo PI, that is /// required by module pass MP. Instantiate analysis pass, by using /// its runOnFunction() for function F. -Pass* MPPassManager::getOnTheFlyPass(Pass *MP, AnalysisID PI, Function &F){ - FunctionPassManagerImpl *FPP = OnTheFlyManagers[MP]; +std::tuple<Pass *, bool> MPPassManager::getOnTheFlyPass(Pass *MP, AnalysisID PI, + Function &F) { + legacy::FunctionPassManagerImpl *FPP = OnTheFlyManagers[MP]; assert(FPP && "Unable to find on the fly pass"); FPP->releaseMemoryOnTheFly(); - FPP->run(F); - return ((PMTopLevelManager*)FPP)->findAnalysisPass(PI); + bool Changed = FPP->run(F); + return std::make_tuple(((PMTopLevelManager *)FPP)->findAnalysisPass(PI), + Changed); } - -//===----------------------------------------------------------------------===// -// PassManagerImpl implementation - -// -/// run - Execute all of the passes scheduled for execution. Keep track of -/// whether any of the passes modifies the module, and if so, return true. -bool PassManagerImpl::run(Module &M) { - bool Changed = false; - - dumpArguments(); - dumpPasses(); - - for (ImmutablePass *ImPass : getImmutablePasses()) - Changed |= ImPass->doInitialization(M); - - initializeAllAnalysisInfo(); - for (unsigned Index = 0; Index < getNumContainedManagers(); ++Index) { - Changed |= getContainedManager(Index)->runOnModule(M); - M.getContext().yield(); - } - - for (ImmutablePass *ImPass : getImmutablePasses()) - Changed |= ImPass->doFinalization(M); - - return Changed; -} +namespace llvm { +namespace legacy { //===----------------------------------------------------------------------===// // PassManager implementation @@ -1724,6 +1823,8 @@ void PassManager::add(Pass *P) { bool PassManager::run(Module &M) { return PM->run(M); } +} // namespace legacy +} // namespace llvm //===----------------------------------------------------------------------===// // PMStack implementation @@ -1814,4 +1915,4 @@ void FunctionPass::assignPassManager(PMStack &PMS, PM->add(this); } -PassManagerBase::~PassManagerBase() {} +legacy::PassManagerBase::~PassManagerBase() {} |