X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FVMCore%2FPassManager.cpp;h=4cf5501379c95894497c8e922fb2da2740dc0bd4;hb=7ee5d354938b231b1d01a76f686ee4dcbfa27600;hp=f10bc6f5ef6f7744c367cf056a9c841b04873405;hpb=9450b0e1a6154192ca597ad27f8eb6e6e807f7a4;p=oota-llvm.git diff --git a/lib/VMCore/PassManager.cpp b/lib/VMCore/PassManager.cpp index f10bc6f5ef6..4cf5501379c 100644 --- a/lib/VMCore/PassManager.cpp +++ b/lib/VMCore/PassManager.cpp @@ -13,13 +13,15 @@ #include "llvm/PassManagers.h" +#include "llvm/Assembly/PrintModulePass.h" #include "llvm/Assembly/Writer.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" #include "llvm/Support/Timer.h" #include "llvm/Module.h" -#include "llvm/ModuleProvider.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/PassNameParser.h" #include "llvm/Support/raw_ostream.h" #include "llvm/System/Mutex.h" #include "llvm/System/Threading.h" @@ -55,6 +57,57 @@ PassDebugging("debug-pass", cl::Hidden, clEnumVal(Executions, "print pass name before it is executed"), clEnumVal(Details , "print pass details when it is executed"), clEnumValEnd)); + +typedef llvm::cl::list +PassOptionList; + +// Print IR out before/after specified passes. +static PassOptionList +PrintBefore("print-before", + llvm::cl::desc("Print IR before specified passes")); + +static PassOptionList +PrintAfter("print-after", + llvm::cl::desc("Print IR after specified passes")); + +static cl::opt +PrintBeforeAll("print-before-all", + llvm::cl::desc("Print IR before each pass"), + cl::init(false)); +static cl::opt +PrintAfterAll("print-after-all", + llvm::cl::desc("Print IR after each pass"), + cl::init(false)); + +/// This is a helper to determine whether to print IR before or +/// after a pass. + +static bool ShouldPrintBeforeOrAfterPass(Pass *P, + PassOptionList &PassesToPrint) { + for (unsigned i = 0, ie = PassesToPrint.size(); i < ie; ++i) { + const llvm::PassInfo *PassInf = PassesToPrint[i]; + if (PassInf && P->getPassInfo()) + if (PassInf->getPassArgument() == + P->getPassInfo()->getPassArgument()) { + return true; + } + } + return false; +} + + +/// This is a utility to check whether a pass should have IR dumped +/// before it. +static bool ShouldPrintBeforePass(Pass *P) { + return PrintBeforeAll || ShouldPrintBeforeOrAfterPass(P, PrintBefore); +} + +/// This is a utility to check whether a pass should have IR dumped +/// after it. +static bool ShouldPrintAfterPass(Pass *P) { + return PrintAfterAll || ShouldPrintBeforeOrAfterPass(P, PrintAfter); +} + } // End of llvm namespace /// isPassDebuggingExecutionsOrMore - Return true if -debug-pass=Executions @@ -105,8 +158,7 @@ namespace { /// BBPassManager manages BasicBlockPass. It batches all the /// pass together and sequence them to process one basic block before /// processing next basic block. -class VISIBILITY_HIDDEN BBPassManager : public PMDataManager, - public FunctionPass { +class BBPassManager : public PMDataManager, public FunctionPass { public: static char ID; @@ -127,13 +179,16 @@ public: bool doFinalization(Module &M); bool doFinalization(Function &F); + virtual PMDataManager *getAsPMDataManager() { return this; } + virtual Pass *getAsPass() { return this; } + virtual const char *getPassName() const { return "BasicBlock Pass Manager"; } // Print passes managed by this manager void dumpPassStructure(unsigned Offset) { - llvm::errs() << std::string(Offset*2, ' ') << "BasicBlockPass Manager\n"; + llvm::dbgs() << std::string(Offset*2, ' ') << "BasicBlockPass Manager\n"; for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) { BasicBlockPass *BP = getContainedPass(Index); BP->dumpPassStructure(Offset + 1); @@ -169,7 +224,7 @@ private: public: static char ID; explicit FunctionPassManagerImpl(int Depth) : - Pass(&ID), PMDataManager(Depth), + Pass(PT_PassManager, &ID), PMDataManager(Depth), PMTopLevelManager(TLM_Function), wasRun(false) { } /// add - Add a pass to the queue of passes to run. This passes ownership of @@ -180,6 +235,11 @@ public: schedulePass(P); } + /// createPrinterPass - Get a function printer pass. + Pass *createPrinterPass(raw_ostream &O, const std::string &Banner) const { + return createPrintFunctionPass(Banner, &O); + } + // Prepare for running an on the fly pass, freeing memory if needed // from a previous run. void releaseMemoryOnTheFly(); @@ -196,15 +256,17 @@ public: /// bool doFinalization(Module &M); + + virtual PMDataManager *getAsPMDataManager() { return this; } + virtual Pass *getAsPass() { return this; } + /// Pass Manager itself does not invalidate any analysis info. void getAnalysisUsage(AnalysisUsage &Info) const { Info.setPreservesAll(); } inline void addTopLevelPass(Pass *P) { - - if (ImmutablePass *IP = dynamic_cast (P)) { - + if (ImmutablePass *IP = P->getAsImmutablePass()) { // P is a immutable pass and it will be managed by this // top level manager. Set up analysis resolver to connect them. AnalysisResolver *AR = new AnalysisResolver(*this); @@ -213,7 +275,7 @@ public: addImmutablePass(IP); recordAvailableAnalysis(IP); } else { - P->assignPassManager(activeStack); + P->assignPassManager(activeStack, PMT_FunctionPassManager); } } @@ -236,7 +298,7 @@ class MPPassManager : public Pass, public PMDataManager { public: static char ID; explicit MPPassManager(int Depth) : - Pass(&ID), PMDataManager(Depth) { } + Pass(PT_PassManager, &ID), PMDataManager(Depth) { } // Delete on the fly managers. virtual ~MPPassManager() { @@ -248,6 +310,11 @@ public: } } + /// createPrinterPass - Get a module printer pass. + Pass *createPrinterPass(raw_ostream &O, const std::string &Banner) const { + return createPrintModulePass(&O, false, Banner); + } + /// 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 runOnModule(Module &M); @@ -271,9 +338,12 @@ public: return "Module Pass Manager"; } + virtual PMDataManager *getAsPMDataManager() { return this; } + virtual Pass *getAsPass() { return this; } + // Print passes managed by this manager void dumpPassStructure(unsigned Offset) { - llvm::errs() << std::string(Offset*2, ' ') << "ModulePass Manager\n"; + llvm::dbgs() << std::string(Offset*2, ' ') << "ModulePass Manager\n"; for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) { ModulePass *MP = getContainedPass(Index); MP->dumpPassStructure(Offset + 1); @@ -313,7 +383,8 @@ class PassManagerImpl : public Pass, public: static char ID; explicit PassManagerImpl(int Depth) : - Pass(&ID), PMDataManager(Depth), PMTopLevelManager(TLM_Pass) { } + Pass(PT_PassManager, &ID), PMDataManager(Depth), + PMTopLevelManager(TLM_Pass) { } /// add - Add a pass to the queue of passes to run. This passes ownership of /// the Pass to the PassManager. When the PassManager is destroyed, the pass @@ -323,6 +394,11 @@ public: schedulePass(P); } + /// createPrinterPass - Get a module printer pass. + Pass *createPrinterPass(raw_ostream &O, const std::string &Banner) const { + return createPrintModulePass(&O, false, Banner); + } + /// 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 run(Module &M); @@ -333,8 +409,7 @@ public: } inline void addTopLevelPass(Pass *P) { - if (ImmutablePass *IP = dynamic_cast (P)) { - + if (ImmutablePass *IP = P->getAsImmutablePass()) { // P is a immutable pass and it will be managed by this // top level manager. Set up analysis resolver to connect them. AnalysisResolver *AR = new AnalysisResolver(*this); @@ -343,10 +418,13 @@ public: addImmutablePass(IP); recordAvailableAnalysis(IP); } else { - P->assignPassManager(activeStack); + P->assignPassManager(activeStack, PMT_ModulePassManager); } } + virtual PMDataManager *getAsPMDataManager() { return this; } + virtual Pass *getAsPass() { return this; } + MPPassManager *getContainedManager(unsigned N) { assert(N < PassManagers.size() && "Pass number out of range!"); MPPassManager *MP = static_cast(PassManagers[N]); @@ -367,18 +445,20 @@ namespace { static ManagedStatic > TimingInfoMutex; -class VISIBILITY_HIDDEN TimingInfo { - std::map TimingData; +class TimingInfo { + DenseMap TimingData; TimerGroup TG; - public: // Use 'create' member to get this. TimingInfo() : TG("... Pass execution timing report ...") {} // TimingDtor - Print out information about timing information ~TimingInfo() { - // Delete all of the timers... - TimingData.clear(); + // Delete all of the timers, which accumulate their info into the + // TimerGroup. + for (DenseMap::iterator I = TimingData.begin(), + E = TimingData.end(); I != E; ++I) + delete I->second; // TimerGroup is deleted next, printing the report. } @@ -387,18 +467,15 @@ public: // null. It may be called multiple times. static void createTheTimeInfo(); - /// passStarted - This method creates a timer for the given pass if it doesn't - /// already have one, and starts the timer. - Timer *passStarted(Pass *P) { - if (dynamic_cast(P)) + /// getPassTimer - Return the timer for the specified pass if it exists. + Timer *getPassTimer(Pass *P) { + if (P->getAsPMDataManager()) return 0; sys::SmartScopedLock Lock(*TimingInfoMutex); - std::map::iterator I = TimingData.find(P); - if (I == TimingData.end()) - I=TimingData.insert(std::make_pair(P, Timer(P->getPassName(), TG))).first; - Timer *T = &I->second; - T->startTimer(); + Timer *&T = TimingData[P]; + if (T == 0) + T = new Timer(P->getPassName(), TG); return T; } }; @@ -561,10 +638,14 @@ Pass *PMTopLevelManager::findAnalysisPass(AnalysisID AID) { // If Pass not found then check the interfaces implemented by Immutable Pass if (!P) { - const std::vector &ImmPI = - PI->getInterfacesImplemented(); - if (std::find(ImmPI.begin(), ImmPI.end(), AID) != ImmPI.end()) - P = *I; + const PassInfo::InterfaceInfo *ImmPI = PI->getInterfacesImplemented(); + while (ImmPI) { + if (ImmPI->interface == AID) { + P = *I; + break; + } else + ImmPI = ImmPI->next; + } } } @@ -584,11 +665,11 @@ void PMTopLevelManager::dumpPasses() const { // Every class that derives from PMDataManager also derives from Pass // (sometimes indirectly), but there's no inheritance relationship - // between PMDataManager and Pass, so we have to dynamic_cast to get + // between PMDataManager and Pass, so we have to getAsPass to get // from a PMDataManager* to a Pass*. for (SmallVector::const_iterator I = PassManagers.begin(), E = PassManagers.end(); I != E; ++I) - dynamic_cast(*I)->dumpPassStructure(1); + (*I)->getAsPass()->dumpPassStructure(1); } void PMTopLevelManager::dumpArguments() const { @@ -596,11 +677,11 @@ void PMTopLevelManager::dumpArguments() const { if (PassDebugging < Arguments) return; - errs() << "Pass Arguments: "; + dbgs() << "Pass Arguments: "; for (SmallVector::const_iterator I = PassManagers.begin(), E = PassManagers.end(); I != E; ++I) (*I)->dumpPassArguments(); - errs() << "\n"; + dbgs() << "\n"; } void PMTopLevelManager::initializeAllAnalysisInfo() { @@ -654,9 +735,11 @@ void PMDataManager::recordAvailableAnalysis(Pass *P) { //This pass is the current implementation of all of the interfaces it //implements as well. - const std::vector &II = PI->getInterfacesImplemented(); - for (unsigned i = 0, e = II.size(); i != e; ++i) - AvailableAnalysis[II[i]] = P; + const PassInfo::InterfaceInfo *II = PI->getInterfacesImplemented(); + while (II) { + AvailableAnalysis[II->interface] = P; + II = II->next; + } } // Return true if P preserves high level analysis used by other @@ -670,7 +753,7 @@ bool PMDataManager::preserveHigherLevelAnalysis(Pass *P) { for (SmallVector::iterator I = HigherLevelAnalysis.begin(), E = HigherLevelAnalysis.end(); I != E; ++I) { Pass *P1 = *I; - if (!dynamic_cast(P1) && + if (P1->getAsImmutablePass() == 0 && std::find(PreservedSet.begin(), PreservedSet.end(), P1->getPassInfo()) == PreservedSet.end()) @@ -694,11 +777,8 @@ void PMDataManager::verifyPreservedAnalysis(Pass *P) { E = PreservedSet.end(); I != E; ++I) { AnalysisID AID = *I; if (Pass *AP = findAnalysisPass(AID, true)) { - - Timer *T = 0; - if (TheTimeInfo) T = TheTimeInfo->passStarted(AP); + TimeRegion PassTimer(getPassTimer(AP)); AP->verifyAnalysis(); - if (T) T->stopTimer(); } } } @@ -713,14 +793,14 @@ void PMDataManager::removeNotPreservedAnalysis(Pass *P) { for (std::map::iterator I = AvailableAnalysis.begin(), E = AvailableAnalysis.end(); I != E; ) { std::map::iterator Info = I++; - if (!dynamic_cast(Info->second) - && std::find(PreservedSet.begin(), PreservedSet.end(), Info->first) == + if (Info->second->getAsImmutablePass() == 0 && + std::find(PreservedSet.begin(), PreservedSet.end(), Info->first) == PreservedSet.end()) { // Remove this analysis if (PassDebugging >= Details) { Pass *S = Info->second; - errs() << " -- '" << P->getPassName() << "' is not preserving '"; - errs() << S->getPassName() << "'\n"; + dbgs() << " -- '" << P->getPassName() << "' is not preserving '"; + dbgs() << S->getPassName() << "'\n"; } AvailableAnalysis.erase(Info); } @@ -737,17 +817,23 @@ void PMDataManager::removeNotPreservedAnalysis(Pass *P) { I = InheritedAnalysis[Index]->begin(), E = InheritedAnalysis[Index]->end(); I != E; ) { std::map::iterator Info = I++; - if (!dynamic_cast(Info->second) && + if (Info->second->getAsImmutablePass() == 0 && std::find(PreservedSet.begin(), PreservedSet.end(), Info->first) == - PreservedSet.end()) + PreservedSet.end()) { // Remove this analysis + if (PassDebugging >= Details) { + Pass *S = Info->second; + dbgs() << " -- '" << P->getPassName() << "' is not preserving '"; + dbgs() << S->getPassName() << "'\n"; + } InheritedAnalysis[Index]->erase(Info); + } } } } /// Remove analysis passes that are not used any longer -void PMDataManager::removeDeadPasses(Pass *P, const StringRef &Msg, +void PMDataManager::removeDeadPasses(Pass *P, StringRef Msg, enum PassDebuggingString DBG_STR) { SmallVector DeadPasses; @@ -759,9 +845,9 @@ void PMDataManager::removeDeadPasses(Pass *P, const StringRef &Msg, TPM->collectLastUses(DeadPasses, P); if (PassDebugging >= Details && !DeadPasses.empty()) { - errs() << " -*- '" << P->getPassName(); - errs() << "' is the last user of following pass instances."; - errs() << " Free these instances\n"; + dbgs() << " -*- '" << P->getPassName(); + dbgs() << "' is the last user of following pass instances."; + dbgs() << " Free these instances\n"; } for (SmallVector::iterator I = DeadPasses.begin(), @@ -769,17 +855,16 @@ void PMDataManager::removeDeadPasses(Pass *P, const StringRef &Msg, freePass(*I, Msg, DBG_STR); } -void PMDataManager::freePass(Pass *P, const StringRef &Msg, +void PMDataManager::freePass(Pass *P, StringRef Msg, enum PassDebuggingString DBG_STR) { dumpPassInfo(P, FREEING_MSG, DBG_STR, Msg); { // If the pass crashes releasing memory, remember this. PassManagerPrettyStackEntry X(P); - - Timer *T = StartPassTimer(P); + TimeRegion PassTimer(getPassTimer(P)); + P->releaseMemory(); - StopPassTimer(P, T); } if (const PassInfo *PI = P->getPassInfo()) { @@ -788,12 +873,13 @@ void PMDataManager::freePass(Pass *P, const StringRef &Msg, // Remove all interfaces this pass implements, for which it is also // listed as the available implementation. - const std::vector &II = PI->getInterfacesImplemented(); - for (unsigned i = 0, e = II.size(); i != e; ++i) { + const PassInfo::InterfaceInfo *II = PI->getInterfacesImplemented(); + while (II) { std::map::iterator Pos = - AvailableAnalysis.find(II[i]); + AvailableAnalysis.find(II->interface); if (Pos != AvailableAnalysis.end() && Pos->second == P) AvailableAnalysis.erase(Pos); + II = II->next; } } } @@ -848,12 +934,12 @@ void PMDataManager::add(Pass *P, bool ProcessAnalysis) { // Set P as P's last user until someone starts using P. // However, if P is a Pass Manager then it does not need // to record its last user. - if (!dynamic_cast(P)) + if (P->getAsPMDataManager() == 0) LastUses.push_back(P); TPM->setLastUser(LastUses, P); if (!TransferLastUses.empty()) { - Pass *My_PM = dynamic_cast(this); + Pass *My_PM = getAsPass(); TPM->setLastUser(TransferLastUses, My_PM); TransferLastUses.clear(); } @@ -954,7 +1040,7 @@ void PMDataManager::dumpLastUses(Pass *P, unsigned Offset) const{ for (SmallVector::iterator I = LUses.begin(), E = LUses.end(); I != E; ++I) { - llvm::errs() << "--" << std::string(Offset*2, ' '); + llvm::dbgs() << "--" << std::string(Offset*2, ' '); (*I)->dumpPassStructure(0); } } @@ -962,49 +1048,49 @@ void PMDataManager::dumpLastUses(Pass *P, unsigned Offset) const{ void PMDataManager::dumpPassArguments() const { for (SmallVector::const_iterator I = PassVector.begin(), E = PassVector.end(); I != E; ++I) { - if (PMDataManager *PMD = dynamic_cast(*I)) + if (PMDataManager *PMD = (*I)->getAsPMDataManager()) PMD->dumpPassArguments(); else if (const PassInfo *PI = (*I)->getPassInfo()) if (!PI->isAnalysisGroup()) - errs() << " -" << PI->getPassArgument(); + dbgs() << " -" << PI->getPassArgument(); } } void PMDataManager::dumpPassInfo(Pass *P, enum PassDebuggingString S1, enum PassDebuggingString S2, - const StringRef &Msg) { + StringRef Msg) { if (PassDebugging < Executions) return; - errs() << (void*)this << std::string(getDepth()*2+1, ' '); + dbgs() << (void*)this << std::string(getDepth()*2+1, ' '); switch (S1) { case EXECUTION_MSG: - errs() << "Executing Pass '" << P->getPassName(); + dbgs() << "Executing Pass '" << P->getPassName(); break; case MODIFICATION_MSG: - errs() << "Made Modification '" << P->getPassName(); + dbgs() << "Made Modification '" << P->getPassName(); break; case FREEING_MSG: - errs() << " Freeing Pass '" << P->getPassName(); + dbgs() << " Freeing Pass '" << P->getPassName(); break; default: break; } switch (S2) { case ON_BASICBLOCK_MSG: - errs() << "' on BasicBlock '" << Msg << "'...\n"; + dbgs() << "' on BasicBlock '" << Msg << "'...\n"; break; case ON_FUNCTION_MSG: - errs() << "' on Function '" << Msg << "'...\n"; + dbgs() << "' on Function '" << Msg << "'...\n"; break; case ON_MODULE_MSG: - errs() << "' on Module '" << Msg << "'...\n"; + dbgs() << "' on Module '" << Msg << "'...\n"; break; case ON_LOOP_MSG: - errs() << "' on Loop '" << Msg << "'...\n"; + dbgs() << "' on Loop '" << Msg << "'...\n"; break; case ON_CG_MSG: - errs() << "' on Call Graph Nodes '" << Msg << "'...\n"; + dbgs() << "' on Call Graph Nodes '" << Msg << "'...\n"; break; default: break; @@ -1029,17 +1115,17 @@ void PMDataManager::dumpPreservedSet(const Pass *P) const { dumpAnalysisUsage("Preserved", P, analysisUsage.getPreservedSet()); } -void PMDataManager::dumpAnalysisUsage(const StringRef &Msg, const Pass *P, +void PMDataManager::dumpAnalysisUsage(StringRef Msg, const Pass *P, const AnalysisUsage::VectorType &Set) const { assert(PassDebugging >= Details); if (Set.empty()) return; - errs() << (void*)P << std::string(getDepth()*2+3, ' ') << Msg << " Analyses:"; + dbgs() << (void*)P << std::string(getDepth()*2+3, ' ') << Msg << " Analyses:"; for (unsigned i = 0; i != Set.size(); ++i) { - if (i) errs() << ','; - errs() << ' ' << Set[i]->getPassName(); + if (i) dbgs() << ','; + dbgs() << ' ' << Set[i]->getPassName(); } - errs() << '\n'; + dbgs() << '\n'; } /// Add RequiredPass into list of lower level passes required by pass P. @@ -1062,12 +1148,17 @@ void PMDataManager::addLowerLevelRequiredPass(Pass *P, Pass *RequiredPass) { // checks whether any lower level manager will be able to provide this // analysis info on demand or not. #ifndef NDEBUG - errs() << "Unable to schedule '" << RequiredPass->getPassName(); - errs() << "' required by '" << P->getPassName() << "'\n"; + dbgs() << "Unable to schedule '" << RequiredPass->getPassName(); + dbgs() << "' required by '" << P->getPassName() << "'\n"; #endif llvm_unreachable("Unable to schedule pass"); } +Pass *PMDataManager::getOnTheFlyPass(Pass *P, const PassInfo *PI, Function &F) { + assert(0 && "Unable to find on the fly pass"); + return NULL; +} + // Destructor PMDataManager::~PMDataManager() { for (SmallVector::iterator I = PassVector.begin(), @@ -1102,6 +1193,7 @@ bool BBPassManager::runOnFunction(Function &F) { for (Function::iterator I = F.begin(), E = F.end(); I != E; ++I) for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) { BasicBlockPass *BP = getContainedPass(Index); + bool LocalChanged = false; dumpPassInfo(BP, EXECUTION_MSG, ON_BASICBLOCK_MSG, I->getName()); dumpRequiredSet(BP); @@ -1111,13 +1203,13 @@ bool BBPassManager::runOnFunction(Function &F) { { // If the pass crashes, remember this. PassManagerPrettyStackEntry X(BP, *I); - - Timer *T = StartPassTimer(BP); - Changed |= BP->runOnBasicBlock(*I); - StopPassTimer(BP, T); + TimeRegion PassTimer(getPassTimer(BP)); + + LocalChanged |= BP->runOnBasicBlock(*I); } - if (Changed) + Changed |= LocalChanged; + if (LocalChanged) dumpPassInfo(BP, MODIFICATION_MSG, ON_BASICBLOCK_MSG, I->getName()); dumpPreservedSet(BP); @@ -1128,7 +1220,7 @@ bool BBPassManager::runOnFunction(Function &F) { removeDeadPasses(BP, I->getName(), ON_BASICBLOCK_MSG); } - return Changed |= doFinalization(F); + return doFinalization(F) || Changed; } // Implement doInitialization and doFinalization @@ -1177,28 +1269,43 @@ bool BBPassManager::doFinalization(Function &F) { // FunctionPassManager implementation /// Create new Function pass manager -FunctionPassManager::FunctionPassManager(ModuleProvider *P) { +FunctionPassManager::FunctionPassManager(Module *m) : M(m) { FPM = new FunctionPassManagerImpl(0); // FPM is the top level manager. FPM->setTopLevelManager(FPM); AnalysisResolver *AR = new AnalysisResolver(*FPM); FPM->setResolver(AR); - - MP = P; } FunctionPassManager::~FunctionPassManager() { delete FPM; } +/// addImpl - Add a pass to the queue of passes to run, without +/// checking whether to add a printer pass. +void FunctionPassManager::addImpl(Pass *P) { + FPM->add(P); +} + /// add - Add a pass to the queue of passes to run. This passes /// ownership of the Pass to the PassManager. When the /// PassManager_X is destroyed, the pass will be destroyed as well, so /// there is no need to delete the pass. (TODO delete passes.) /// This implies that all passes MUST be allocated with 'new'. void FunctionPassManager::add(Pass *P) { - FPM->add(P); + // If this is a not a function pass, don't add a printer for it. + if (P->getPassKind() == PT_Function) + if (ShouldPrintBeforePass(P)) + addImpl(P->createPrinterPass(dbgs(), std::string("*** IR Dump Before ") + + P->getPassName() + " ***")); + + addImpl(P); + + if (P->getPassKind() == PT_Function) + if (ShouldPrintAfterPass(P)) + addImpl(P->createPrinterPass(dbgs(), std::string("*** IR Dump After ") + + P->getPassName() + " ***")); } /// run - Execute all of the passes scheduled for execution. Keep @@ -1206,9 +1313,10 @@ void FunctionPassManager::add(Pass *P) { /// so, return true. /// bool FunctionPassManager::run(Function &F) { - std::string errstr; - if (MP->materializeFunction(&F, &errstr)) { - llvm_report_error("Error reading bitcode file: " + errstr); + if (F.isMaterializable()) { + std::string errstr; + if (F.Materialize(&errstr)) + report_fatal_error("Error reading bitcode file: " + Twine(errstr)); } return FPM->run(F); } @@ -1217,13 +1325,13 @@ bool FunctionPassManager::run(Function &F) { /// doInitialization - Run all of the initializers for the function passes. /// bool FunctionPassManager::doInitialization() { - return FPM->doInitialization(*MP->getModule()); + return FPM->doInitialization(*M); } /// doFinalization - Run all of the finalizers for the function passes. /// bool FunctionPassManager::doFinalization() { - return FPM->doFinalization(*MP->getModule()); + return FPM->doFinalization(*M); } //===----------------------------------------------------------------------===// @@ -1232,6 +1340,9 @@ bool FunctionPassManager::doFinalization() { bool FunctionPassManagerImpl::doInitialization(Module &M) { bool Changed = false; + dumpArguments(); + dumpPasses(); + for (unsigned Index = 0; Index < getNumContainedManagers(); ++Index) Changed |= getContainedManager(Index)->doInitialization(M); @@ -1275,9 +1386,6 @@ bool FunctionPassManagerImpl::run(Function &F) { bool Changed = false; TimingInfo::createTheTimeInfo(); - dumpArguments(); - dumpPasses(); - initializeAllAnalysisInfo(); for (unsigned Index = 0; Index < getNumContainedManagers(); ++Index) Changed |= getContainedManager(Index)->runOnFunction(F); @@ -1295,7 +1403,7 @@ bool FunctionPassManagerImpl::run(Function &F) { char FPPassManager::ID = 0; /// Print passes managed by this manager void FPPassManager::dumpPassStructure(unsigned Offset) { - llvm::errs() << std::string(Offset*2, ' ') << "FunctionPass Manager\n"; + llvm::dbgs() << std::string(Offset*2, ' ') << "FunctionPass Manager\n"; for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) { FunctionPass *FP = getContainedPass(Index); FP->dumpPassStructure(Offset + 1); @@ -1318,6 +1426,7 @@ bool FPPassManager::runOnFunction(Function &F) { for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) { FunctionPass *FP = getContainedPass(Index); + bool LocalChanged = false; dumpPassInfo(FP, EXECUTION_MSG, ON_FUNCTION_MSG, F.getName()); dumpRequiredSet(FP); @@ -1326,13 +1435,13 @@ bool FPPassManager::runOnFunction(Function &F) { { PassManagerPrettyStackEntry X(FP, F); + TimeRegion PassTimer(getPassTimer(FP)); - Timer *T = StartPassTimer(FP); - Changed |= FP->runOnFunction(F); - StopPassTimer(FP, T); + LocalChanged |= FP->runOnFunction(F); } - if (Changed) + Changed |= LocalChanged; + if (LocalChanged) dumpPassInfo(FP, MODIFICATION_MSG, ON_FUNCTION_MSG, F.getName()); dumpPreservedSet(FP); @@ -1350,7 +1459,7 @@ bool FPPassManager::runOnModule(Module &M) { for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) runOnFunction(*I); - return Changed |= doFinalization(M); + return doFinalization(M) || Changed; } bool FPPassManager::doInitialization(Module &M) { @@ -1391,29 +1500,30 @@ MPPassManager::runOnModule(Module &M) { for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) { ModulePass *MP = getContainedPass(Index); + bool LocalChanged = false; - dumpPassInfo(MP, EXECUTION_MSG, ON_MODULE_MSG, - M.getModuleIdentifier().c_str()); + dumpPassInfo(MP, EXECUTION_MSG, ON_MODULE_MSG, M.getModuleIdentifier()); dumpRequiredSet(MP); initializeAnalysisImpl(MP); { PassManagerPrettyStackEntry X(MP, M); - Timer *T = StartPassTimer(MP); - Changed |= MP->runOnModule(M); - StopPassTimer(MP, T); + TimeRegion PassTimer(getPassTimer(MP)); + + LocalChanged |= MP->runOnModule(M); } - if (Changed) + Changed |= LocalChanged; + if (LocalChanged) dumpPassInfo(MP, MODIFICATION_MSG, ON_MODULE_MSG, - M.getModuleIdentifier().c_str()); + M.getModuleIdentifier()); dumpPreservedSet(MP); verifyPreservedAnalysis(MP); removeNotPreservedAnalysis(MP); recordAvailableAnalysis(MP); - removeDeadPasses(MP, M.getModuleIdentifier().c_str(), ON_MODULE_MSG); + removeDeadPasses(MP, M.getModuleIdentifier(), ON_MODULE_MSG); } // Finalize on-the-fly passes @@ -1464,7 +1574,7 @@ Pass* MPPassManager::getOnTheFlyPass(Pass *MP, const PassInfo *PI, Function &F){ FPP->releaseMemoryOnTheFly(); FPP->run(F); - return (dynamic_cast(FPP))->findAnalysisPass(PI); + return ((PMTopLevelManager*)FPP)->findAnalysisPass(PI); } @@ -1500,12 +1610,26 @@ PassManager::~PassManager() { delete PM; } +/// addImpl - Add a pass to the queue of passes to run, without +/// checking whether to add a printer pass. +void PassManager::addImpl(Pass *P) { + PM->add(P); +} + /// add - Add a pass to the queue of passes to run. This passes ownership of /// the Pass to the PassManager. When the PassManager is destroyed, the pass /// will be destroyed as well, so there is no need to delete the pass. This /// implies that all passes MUST be allocated with 'new'. void PassManager::add(Pass *P) { - PM->add(P); + if (ShouldPrintBeforePass(P)) + addImpl(P->createPrinterPass(dbgs(), std::string("*** IR Dump Before ") + + P->getPassName() + " ***")); + + addImpl(P); + + if (ShouldPrintAfterPass(P)) + addImpl(P->createPrinterPass(dbgs(), std::string("*** IR Dump After ") + + P->getPassName() + " ***")); } /// run - Execute all of the passes scheduled for execution. Keep track of @@ -1538,17 +1662,12 @@ void TimingInfo::createTheTimeInfo() { } /// If TimingInfo is enabled then start pass timer. -Timer *llvm::StartPassTimer(Pass *P) { +Timer *llvm::getPassTimer(Pass *P) { if (TheTimeInfo) - return TheTimeInfo->passStarted(P); + return TheTimeInfo->getPassTimer(P); return 0; } -/// If TimingInfo is enabled then stop pass timer. -void llvm::StopPassTimer(Pass *P, Timer *T) { - if (T) T->stopTimer(); -} - //===----------------------------------------------------------------------===// // PMStack implementation // @@ -1581,7 +1700,7 @@ void PMStack::push(PMDataManager *PM) { void PMStack::dump() { for (std::deque::iterator I = S.begin(), E = S.end(); I != E; ++I) - printf("%s ", dynamic_cast(*I)->getPassName()); + printf("%s ", (*I)->getAsPass()->getPassName()); if (!S.empty()) printf("\n"); @@ -1611,16 +1730,18 @@ void FunctionPass::assignPassManager(PMStack &PMS, PassManagerType PreferredType) { // Find Module Pass Manager - while(!PMS.empty()) { + while (!PMS.empty()) { if (PMS.top()->getPassManagerType() > PMT_FunctionPassManager) PMS.pop(); else break; } - FPPassManager *FPP = dynamic_cast(PMS.top()); - // Create new Function Pass Manager - if (!FPP) { + // Create new Function Pass Manager if needed. + FPPassManager *FPP; + if (PMS.top()->getPassManagerType() == PMT_FunctionPassManager) { + FPP = (FPPassManager *)PMS.top(); + } else { assert(!PMS.empty() && "Unable to create Function Pass Manager"); PMDataManager *PMD = PMS.top(); @@ -1648,17 +1769,16 @@ void FunctionPass::assignPassManager(PMStack &PMS, /// in the PM Stack and add self into that manager. void BasicBlockPass::assignPassManager(PMStack &PMS, PassManagerType PreferredType) { - BBPassManager *BBP = NULL; + BBPassManager *BBP; // Basic Pass Manager is a leaf pass manager. It does not handle // any other pass manager. - if (!PMS.empty()) - BBP = dynamic_cast(PMS.top()); - - // If leaf manager is not Basic Block Pass manager then create new - // basic Block Pass manager. - - if (!BBP) { + if (!PMS.empty() && + PMS.top()->getPassManagerType() == PMT_BasicBlockPassManager) { + BBP = (BBPassManager *)PMS.top(); + } else { + // If leaf manager is not Basic Block Pass manager then create new + // basic Block Pass manager. assert(!PMS.empty() && "Unable to create BasicBlock Pass Manager"); PMDataManager *PMD = PMS.top(); @@ -1672,7 +1792,7 @@ void BasicBlockPass::assignPassManager(PMStack &PMS, // [3] Assign manager to manage this new manager. This may create // and push new managers into PMS - BBP->assignPassManager(PMS); + BBP->assignPassManager(PMS, PreferredType); // [4] Push new manager into PMS PMS.push(BBP); @@ -1690,23 +1810,28 @@ LLVMPassManagerRef LLVMCreatePassManager() { return wrap(new PassManager()); } +LLVMPassManagerRef LLVMCreateFunctionPassManagerForModule(LLVMModuleRef M) { + return wrap(new FunctionPassManager(unwrap(M))); +} + LLVMPassManagerRef LLVMCreateFunctionPassManager(LLVMModuleProviderRef P) { - return wrap(new FunctionPassManager(unwrap(P))); + return LLVMCreateFunctionPassManagerForModule( + reinterpret_cast(P)); } -int LLVMRunPassManager(LLVMPassManagerRef PM, LLVMModuleRef M) { +LLVMBool LLVMRunPassManager(LLVMPassManagerRef PM, LLVMModuleRef M) { return unwrap(PM)->run(*unwrap(M)); } -int LLVMInitializeFunctionPassManager(LLVMPassManagerRef FPM) { +LLVMBool LLVMInitializeFunctionPassManager(LLVMPassManagerRef FPM) { return unwrap(FPM)->doInitialization(); } -int LLVMRunFunctionPassManager(LLVMPassManagerRef FPM, LLVMValueRef F) { +LLVMBool LLVMRunFunctionPassManager(LLVMPassManagerRef FPM, LLVMValueRef F) { return unwrap(FPM)->run(*unwrap(F)); } -int LLVMFinalizeFunctionPassManager(LLVMPassManagerRef FPM) { +LLVMBool LLVMFinalizeFunctionPassManager(LLVMPassManagerRef FPM) { return unwrap(FPM)->doFinalization(); }