diff --git a/include/llvm/Pass.h b/include/llvm/Pass.h index 2c82e565ba8..b3ac33485d5 100644 --- a/include/llvm/Pass.h +++ b/include/llvm/Pass.h @@ -31,6 +31,7 @@ #include "llvm/Support/Streams.h" #include +#include #include #include #include @@ -49,6 +50,7 @@ template class PassManagerT; class BasicBlockPassManager; class FunctionPassManagerT; class ModulePassManager; +class PMStack; class AnalysisResolver; // AnalysisID - Use the PassInfo to identify a pass... @@ -133,8 +135,6 @@ public: // dumpPassStructure - Implement the -debug-passes=PassStructure option virtual void dumpPassStructure(unsigned Offset = 0); - - // getPassInfo - Static method to get the pass information from a class name. template static const PassInfo *getClassPassInfo() { return lookupPassInfo(typeid(AnalysisClass)); @@ -198,6 +198,7 @@ public: virtual bool runPass(Module &M) { return runOnModule(M); } virtual bool runPass(BasicBlock&) { return false; } + virtual void assignPassManager(PMStack &PMS); // Force out-of-line virtual method. virtual ~ModulePass(); }; @@ -263,6 +264,7 @@ public: /// bool run(Function &F); + virtual void assignPassManager(PMStack &PMS); }; @@ -316,8 +318,36 @@ public: virtual bool runPass(Module &M) { return false; } virtual bool runPass(BasicBlock &BB); + virtual void assignPassManager(PMStack &PMS); }; +/// PMStack +/// Top level pass manager (see PasManager.cpp) maintains active Pass Managers +/// using PMStack. Each Pass implements assignPassManager() to connect itself +/// with appropriate manager. assignPassManager() walks PMStack to find +/// suitable manager. +/// +/// PMStack is just a wrapper around standard deque that overrides pop() and +/// push() methods. +class PMDataManager; +class PMStack { +public: + typedef std::deque::reverse_iterator iterator; + iterator begin() { return S.rbegin(); } + iterator end() { return S.rend(); } + + void handleLastUserOverflow(); + + void pop(); + inline PMDataManager *top() { return S.back(); } + void push(PMDataManager *PM); + inline bool empty() { return S.empty(); } + +private: + std::deque S; +}; + + /// If the user specifies the -time-passes argument on an LLVM tool command line /// then the value of this boolean will be true, otherwise false. /// @brief This is the storage for the -time-passes option. diff --git a/lib/VMCore/PassManager.cpp b/lib/VMCore/PassManager.cpp index faab37e3de7..46ad33bf964 100644 --- a/lib/VMCore/PassManager.cpp +++ b/lib/VMCore/PassManager.cpp @@ -1514,7 +1514,9 @@ MPPassManager::runOnModule(Module &M) { bool PassManagerImpl::addPass(Pass *P) { if (!activeManager || !activeManager->addPass(P)) { + activeManager = new MPPassManager(getDepth() + 1); + // Inherit top level manager activeManager->setTopLevelManager(this->getTopLevelManager()); @@ -1601,4 +1603,140 @@ void TimingInfo::createTheTimeInfo() { TheTimeInfo = &*TTI; } +//===----------------------------------------------------------------------===// +// PMStack implementation +// +// Pop Pass Manager from the stack and clear its analysis info. +void PMStack::pop() { + + PMDataManager *Top = this->top(); + Top->initializeAnalysisInfo(); + + S.pop_back(); +} + +// Push PM on the stack and set its top level manager. +void PMStack::push(PMDataManager *PM) { + + PMDataManager *Top = this->top(); + + // Inherit top level manager + PMTopLevelManager *TPM = Top->getTopLevelManager(); + PM->setTopLevelManager(TPM); + TPM->addIndirectPassManager(PM); +} + +// Walk Pass Manager stack and set LastUse markers if any +// manager is transfering this priviledge to its parent manager +void PMStack::handleLastUserOverflow() { + + for(PMStack::iterator I = this->begin(), E = this->end(); I != E;) { + + PMDataManager *Child = *I++; + if (I != E) { + PMDataManager *Parent = *I++; + PMTopLevelManager *TPM = Parent->getTopLevelManager(); + std::vector &TLU = Child->getTransferredLastUses(); + if (!TLU.empty()) { + Pass *P = dynamic_cast(Parent); + TPM->setLastUser(TLU, P); + } + } + } +} + +/// Find appropriate Module Pass Manager in the PM Stack and +/// add self into that manager. +void ModulePass::assignPassManager(PMStack &PMS) { + + MPPassManager *MPP = NULL; + + // Find Module Pass Manager + while(!PMS.empty()) { + + MPP = dynamic_cast(PMS.top()); + if (MPP) + break; // Found it + else + PMS.pop(); // Pop children pass managers + } + + assert(MPP && "Unable to find Module Pass Manager"); + + MPP->addPassToManager(this); +} + +/// Find appropriate Function Pass Manager or Call Graph Pass Manager +/// in the PM Stack and add self into that manager. +void FunctionPass::assignPassManager(PMStack &PMS) { + + FPPassManager *FPP = NULL; + + // Find Module Pass Manager + while(!PMS.empty()) { + + FPP = dynamic_cast(PMS.top()); + if (FPP || dynamic_cast(PMS.top())) + break; // Found it or it is not here + else + PMS.pop(); // Pop children pass managers + } + + if (!FPP) { + /// Create new Function Pass Manager + + /// Function Pass Manager does not live by itself + assert(!PMS.empty() && "Unable to create Function Pass Manager"); + + PMDataManager *PMD = PMS.top(); + + /// PMD should be either Module Pass Manager or Call Graph Pass Manager + assert(dynamic_cast(PMD) && + "Unable to create Function Pass Manager"); + + FPP = new FPPassManager(PMD->getDepth() + 1); + PMD->addPassToManager(FPP, false); + PMS.push(FPP); + } + + + FPP->addPassToManager(this); +} + +/// Find appropriate Basic Pass Manager or Call Graph Pass Manager +/// in the PM Stack and add self into that manager. +void BasicBlockPass::assignPassManager(PMStack &PMS) { + + BBPassManager *BBP = NULL; + + // Find Module Pass Manager + while(!PMS.empty()) { + + BBP = dynamic_cast(PMS.top()); + if (BBP || dynamic_cast(PMS.top())) + break; // Found it or it is not here + else + PMS.pop(); // Pop children pass managers + } + + if (!BBP) { + /// Create new BasicBlock Pass Manager + + /// BasicBlock Pass Manager does not live by itself + assert(!PMS.empty() && "Unable to create BasicBlock Pass Manager"); + + PMDataManager *PMD = PMS.top(); + + /// PMD should be Function Pass Manager + assert(dynamic_cast(PMD) && + "Unable to create BasicBlock Pass Manager"); + + BBP = new BBPassManager(PMD->getDepth() + 1); + PMD->addPassToManager(BBP, false); + PMS.push(BBP); + } + + BBP->addPassToManager(this); +} +