diff --git a/include/llvm/Pass.h b/include/llvm/Pass.h index 08899eda0e7..f43db85cbbd 100644 --- a/include/llvm/Pass.h +++ b/include/llvm/Pass.h @@ -18,21 +18,80 @@ #ifndef LLVM_PASS_H #define LLVM_PASS_H -#include "llvm/Module.h" -#include "llvm/Method.h" - -class MethodPassBatcher; +#include +#include +class Value; +class BasicBlock; +class Method; +class Module; +class AnalysisID; +class Pass; +template class PassManagerT; +struct AnalysisResolver; //===----------------------------------------------------------------------===// // Pass interface - Implemented by all 'passes'. Subclass this if you are an // interprocedural optimization or you do not fit into any of the more // constrained passes described below. // -struct Pass { - // Destructor - Virtual so we can be subclassed - inline virtual ~Pass() {} +class Pass { + friend class AnalysisResolver; + AnalysisResolver *Resolver; // AnalysisResolver this pass is owned by... +public: + typedef std::vector AnalysisSet; + inline Pass(AnalysisResolver *AR = 0) : Resolver(AR) {} + inline virtual ~Pass() {} // Destructor is virtual so we can be subclassed + + + // run - Run this pass, returning true if a modification was made to the + // module argument. This should be implemented by all concrete subclasses. + // virtual bool run(Module *M) = 0; + + // getAnalysisUsageInfo - This function should be overriden by passes that + // need analysis information to do their job. If a pass specifies that it + // uses a particular analysis result to this function, it can then use the + // getAnalysis() function, below. + // + // The Destroyed vector is used to communicate what analyses are invalidated + // by this pass. This is critical to specify so that the PassManager knows + // which analysis must be rerun after this pass has proceeded. Analysis are + // only invalidated if run() returns true. + // + // The Provided vector is used for passes that provide analysis information, + // these are the analysis passes themselves. All analysis passes should + // override this method to return themselves in the provided set. + // + virtual void getAnalysisUsageInfo(AnalysisSet &Required, + AnalysisSet &Destroyed, + AnalysisSet &Provided) { + // By default, no analysis results are used or destroyed. + } + +#ifndef NDEBUG + // dumpPassStructure - Implement the -debug-passes=PassStructure option + virtual void dumpPassStructure(unsigned Offset = 0); +#endif + +protected: + // getAnalysis() - This function is used by subclasses to get to + // the analysis information that they claim to use by overriding the + // getAnalysisUsageInfo function. + // + template + AnalysisType &getAnalysis(AnalysisID AID = AnalysisType::ID) { + assert(Resolver && "Pass not resident in a PassManager object!"); + return *(AnalysisType*)Resolver->getAnalysis(AID); + } + +private: + friend class PassManagerT; + friend class PassManagerT; + friend class PassManagerT; + virtual void addToPassManager(PassManagerT *PM, + AnalysisSet &Destroyed, + AnalysisSet &Provided); }; @@ -60,40 +119,27 @@ struct MethodPass : public Pass { // virtual bool doFinalization(Module *M) { return false; } + // run - On a module, we run this pass by initializing, ronOnMethod'ing once + // for every method in the module, then by finalizing. + // + virtual bool run(Module *M); - virtual bool run(Module *M) { - bool Changed = doInitialization(M); + // run - On a method, we simply initialize, run the method, then finalize. + // + bool run(Method *M); - for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) - Changed |= runOnMethod(*I); - - return Changed | doFinalization(M); - } - - bool run(Method *M) { - return doInitialization(M->getParent()) | runOnMethod(M) - | doFinalization(M->getParent()); - } +private: + friend class PassManagerT; + friend class PassManagerT; + friend class PassManagerT; + virtual void addToPassManager(PassManagerT *PM,AnalysisSet &Destroyed, + AnalysisSet &Provided); + virtual void addToPassManager(PassManagerT *PM,AnalysisSet &Destroyed, + AnalysisSet &Provided); }; -//===----------------------------------------------------------------------===// -// CFGSafeMethodPass class - This class is used to implement global -// optimizations that do not modify the CFG of a method. Optimizations should -// subclass this class if they meet the following constraints: -// 1. Optimizations are global, operating on a method at a time. -// 2. Optimizations do not modify the CFG of the contained method, by adding, -// removing, or changing the order of basic blocks in a method. -// 3. Optimizations conform to all of the contstraints of MethodPass's. -// -struct CFGSafeMethodPass : public MethodPass { - - // TODO: Differentiation from MethodPass will come later - -}; - - //===----------------------------------------------------------------------===// // BasicBlockPass class - This class is used to implement most local // optimizations. Optimizations should subclass this class if they @@ -102,52 +148,98 @@ struct CFGSafeMethodPass : public MethodPass { // instruction at a time. // 2. Optimizations do not modify the CFG of the contained method, or any // other basic block in the method. -// 3. Optimizations conform to all of the contstraints of CFGSafeMethodPass's. +// 3. Optimizations conform to all of the contstraints of MethodPass's. // -struct BasicBlockPass : public CFGSafeMethodPass { +struct BasicBlockPass : public MethodPass { // runOnBasicBlock - Virtual method overriden by subclasses to do the // per-basicblock processing of the pass. // virtual bool runOnBasicBlock(BasicBlock *M) = 0; - virtual bool runOnMethod(Method *M) { - bool Changed = false; - for (Method::iterator I = M->begin(), E = M->end(); I != E; ++I) - Changed |= runOnBasicBlock(*I); - return Changed; + // To run this pass on a method, we simply call runOnBasicBlock once for each + // method. + // + virtual bool runOnMethod(Method *BB); + + // To run directly on the basic block, we initialize, runOnBasicBlock, then + // finalize. + // + bool run(BasicBlock *BB); + +private: + friend class PassManagerT; + friend class PassManagerT; + virtual void addToPassManager(PassManagerT *PM,AnalysisSet &Destroyed, + AnalysisSet &Provided); + virtual void addToPassManager(PassManagerT *PM, + AnalysisSet &Destroyed, + AnalysisSet &Provided); +}; + + +// CreatePass - Helper template to invoke the constructor for the AnalysisID +// class. Note that this should be a template internal to AnalysisID, but +// GCC 2.95.3 crashes if we do that, doh. +// +template +static Pass *CreatePass(AnalysisID ID) { return new AnalysisType(ID); } + +//===----------------------------------------------------------------------===// +// AnalysisID - This class is used to uniquely identify an analysis pass that +// is referenced by a transformation. +// +class AnalysisID { + static unsigned NextID; // Next ID # to deal out... + unsigned ID; // Unique ID for this analysis + Pass *(*Constructor)(AnalysisID); // Constructor to return the Analysis + + AnalysisID(); // Disable default ctor + AnalysisID(unsigned id, Pass *(*Ct)(AnalysisID)) : ID(id), Constructor(Ct) {} +public: + // create - the only way to define a new AnalysisID. This static method is + // supposed to be used to define the class static AnalysisID's that are + // provided by analysis passes. In the implementation (.cpp) file for the + // class, there should be a line that looks like this (using CallGraph as an + // example): + // + // AnalysisID CallGraph::ID(AnalysisID::create()); + // + template + static AnalysisID create() { + return AnalysisID(NextID++, CreatePass); } - bool run(BasicBlock *BB) { - Module *M = BB->getParent()->getParent(); - return doInitialization(M) | runOnBasicBlock(BB) | doFinalization(M); + inline Pass *createPass() const { return Constructor(*this); } + + inline bool operator==(const AnalysisID &A) const { + return A.ID == ID; + } + inline bool operator!=(const AnalysisID &A) const { + return A.ID != ID; + } + inline bool operator<(const AnalysisID &A) const { + return ID < A.ID; } }; //===----------------------------------------------------------------------===// -// PassManager - Container object for passes. The PassManager destructor -// deletes all passes contained inside of the PassManager, so you shouldn't -// delete passes manually, and all passes should be dynamically allocated. +// AnalysisResolver - Simple interface implemented by PassManagers objects that +// is used to pull analysis information out of them. // -class PassManager { - std::vector Passes; - MethodPassBatcher *Batcher; -public: - PassManager() : Batcher(0) {} - ~PassManager(); - - // run - Run all of the queued passes on the specified module in an optimal - // way. - bool run(Module *M); - - // 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. Also, - // all passes MUST be new'd. - // - void add(Pass *P); - void add(MethodPass *P); - void add(BasicBlockPass *P); +struct AnalysisResolver { + virtual Pass *getAnalysisOrNullUp(AnalysisID ID) = 0; + virtual Pass *getAnalysisOrNullDown(AnalysisID ID) = 0; + Pass *getAnalysis(AnalysisID ID) { + Pass *Result = getAnalysisOrNullUp(ID); + assert(Result && "Pass has an incorrect analysis uses set!"); + return Result; + } + virtual unsigned getDepth() const = 0; +protected: + void setAnalysisResolver(Pass *P, AnalysisResolver *AR); }; + + #endif diff --git a/lib/VMCore/PassManagerT.h b/lib/VMCore/PassManagerT.h new file mode 100644 index 00000000000..07bf738fcdc --- /dev/null +++ b/lib/VMCore/PassManagerT.h @@ -0,0 +1,395 @@ +//===- llvm/PassManager.h - Container for Passes -----------------*- C++ -*--=// +// +// This file defines the PassManager class. This class is used to hold, +// maintain, and optimize execution of Pass's. The PassManager class ensures +// that analysis results are available before a pass runs, and that Pass's are +// destroyed when the PassManager is destroyed. +// +// The PassManagerT template is instantiated three times to do its job. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_PASSMANAGER_H +#define LLVM_PASSMANAGER_H + +#include "llvm/Pass.h" +#include + +// PassManager - Top level PassManagerT instantiation intended to be used. +typedef PassManagerT PassManager; + + +//===----------------------------------------------------------------------===// +// PMDebug class - a set of debugging functions that are enabled when compiling +// with -g on. If compiling at -O, all functions are inlined noops. +// +struct PMDebug { +#ifdef NDEBUG + inline static void PrintPassStructure(Pass *) {} + inline static void PrintPassInformation(unsigned,const char*,Pass*,Value*) {} + inline static void PrintAnalysisSetInfo(unsigned,const char*, + const Pass::AnalysisSet &) {} +#else + // If compiled in debug mode, these functions can be enabled by setting + // -debug-pass on the command line of the tool being used. + // + static void PrintPassStructure(Pass *P); + static void PrintPassInformation(unsigned,const char*,Pass *, Value *); + static void PrintAnalysisSetInfo(unsigned,const char*,const Pass::AnalysisSet&); +#endif +}; + + + +//===----------------------------------------------------------------------===// +// Declare the PassManagerTraits which will be specialized... +// +template class PassManagerTraits; // Do not define. + + +//===----------------------------------------------------------------------===// +// PassManagerT - Container object for passes. The PassManagerT destructor +// deletes all passes contained inside of the PassManagerT, so you shouldn't +// delete passes manually, and all passes should be dynamically allocated. +// +template +class PassManagerT : public PassManagerTraits,public AnalysisResolver{ + typedef typename PassManagerTraits::PassClass PassClass; + typedef typename PassManagerTraits::SubPassClass SubPassClass; + typedef typename PassManagerTraits::BatcherClass BatcherClass; + typedef typename PassManagerTraits::ParentClass ParentClass; + typedef PassManagerTraits Traits; + + friend typename PassManagerTraits::PassClass; + friend typename PassManagerTraits::SubPassClass; + friend class PassManagerTraits; + + std::vector Passes; // List of pass's to run + + // The parent of this pass manager... + const ParentClass *Parent; + + // The current batcher if one is in use, or null + BatcherClass *Batcher; + + // CurrentAnalyses - As the passes are being run, this map contains the + // analyses that are available to the current pass for use. This is accessed + // through the getAnalysis() function in this class and in Pass. + // + std::map CurrentAnalyses; + +public: + PassManagerT(ParentClass *Par = 0) : Parent(Par), Batcher(0) {} + ~PassManagerT() { + // Delete all of the contained passes... + for (std::vector::iterator I = Passes.begin(), E = Passes.end(); + I != E; ++I) + delete *I; + } + + // run - Run all of the queued passes on the specified module in an optimal + // way. + virtual bool runOnUnit(UnitType *M) { + bool MadeChanges = false; + closeBatcher(); + CurrentAnalyses.clear(); + + // Output debug information... + if (Parent == 0) PMDebug::PrintPassStructure(this); + + // Run all of the passes + for (unsigned i = 0, e = Passes.size(); i < e; ++i) { + PassClass *P = Passes[i]; + + PMDebug::PrintPassInformation(getDepth(), "Executing Pass", P, (Value*)M); + + // Get information about what analyses the pass uses... + std::vector Required, Destroyed, Provided; + P->getAnalysisUsageInfo(Required, Destroyed, Provided); + + PMDebug::PrintAnalysisSetInfo(getDepth(), "Required", Required); + +#ifndef NDEBUG + // All Required analyses should be available to the pass as it runs! + for (Pass::AnalysisSet::iterator I = Required.begin(), + E = Required.end(); I != E; ++I) { + assert(getAnalysisOrNullUp(*I) && "Analysis used but not available!"); + } +#endif + + // Run the sub pass! + MadeChanges |= Traits::runPass(P, M); + + PMDebug::PrintAnalysisSetInfo(getDepth(), "Destroyed", Destroyed); + PMDebug::PrintAnalysisSetInfo(getDepth(), "Provided", Provided); + + // Erase all analyses in the destroyed set... + for (Pass::AnalysisSet::iterator I = Destroyed.begin(), + E = Destroyed.end(); I != E; ++I) + CurrentAnalyses.erase(*I); + + // Add all analyses in the provided set... + for (Pass::AnalysisSet::iterator I = Provided.begin(), + E = Provided.end(); I != E; ++I) + CurrentAnalyses[*I] = P; + } + return MadeChanges; + } + + // 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. Also, + // all passes MUST be new'd. + // + void add(PassClass *P) { + // Get information about what analyses the pass uses... + std::vector Required, Destroyed, Provided; + P->getAnalysisUsageInfo(Required, Destroyed, Provided); + + // Loop over all of the analyses used by this pass, + for (std::vector::iterator I = Required.begin(), + E = Required.end(); I != E; ++I) { + if (getAnalysisOrNullDown(*I) == 0) + add(I->createPass()); + } + + // Tell the pass to add itself to this PassManager... the way it does so + // depends on the class of the pass, and is critical to laying out passes in + // an optimal order.. + // + P->addToPassManager(this, Destroyed, Provided); + } + +#ifndef NDEBUG + // dumpPassStructure - Implement the -debug-passes=PassStructure option + virtual void dumpPassStructure(unsigned Offset = 0) { + std::cerr << std::string(Offset*2, ' ') << "Pass Manager\n"; + for (std::vector::iterator I = Passes.begin(), E = Passes.end(); + I != E; ++I) + (*I)->dumpPassStructure(Offset+1); + } +#endif + +public: + Pass *getAnalysisOrNullDown(AnalysisID ID) { + std::map::iterator I = CurrentAnalyses.find(ID); + if (I == CurrentAnalyses.end()) { + if (Batcher) + return ((AnalysisResolver*)Batcher)->getAnalysisOrNullDown(ID); + return 0; + } + return I->second; + } + + Pass *getAnalysisOrNullUp(AnalysisID ID) { + std::map::iterator I = CurrentAnalyses.find(ID); + if (I == CurrentAnalyses.end()) { + if (Parent) + return ((AnalysisResolver*)Parent)->getAnalysisOrNullUp(ID); + return 0; + } + return I->second; + } + + virtual unsigned getDepth() const { + if (Parent == 0) return 0; + return 1 + ((AnalysisResolver*)Parent)->getDepth(); + } + +private: + + // addPass - These functions are used to implement the subclass specific + // behaviors present in PassManager. Basically the add(Pass*) method ends up + // reflecting its behavior into a Pass::addToPassManager call. Subclasses of + // Pass override it specifically so that they can reflect the type + // information inherent in "this" back to the PassManager. + // + // For generic Pass subclasses (which are interprocedural passes), we simply + // add the pass to the end of the pass list and terminate any accumulation of + // MethodPasses that are present. + // + void addPass(PassClass *P, Pass::AnalysisSet &Destroyed, + Pass::AnalysisSet &Provided) { + // Providers are analysis classes which are forbidden to modify the module + // they are operating on, so they are allowed to be reordered to before the + // batcher... + // + if (Batcher && Provided.empty()) + closeBatcher(); // This pass cannot be batched! + + // Set the Resolver instance variable in the Pass so that it knows where to + // find this object... + // + setAnalysisResolver(P, this); + Passes.push_back(P); + + // Erase all analyses in the destroyed set... + for (std::vector::iterator I = Destroyed.begin(), + E = Destroyed.end(); I != E; ++I) + CurrentAnalyses.erase(*I); + + // Add all analyses in the provided set... + for (std::vector::iterator I = Provided.begin(), + E = Provided.end(); I != E; ++I) + CurrentAnalyses[*I] = P; + } + + // For MethodPass subclasses, we must be sure to batch the MethodPasses + // together in a MethodPassBatcher object so that all of the analyses are run + // together a method at a time. + // + void addPass(SubPassClass *MP, Pass::AnalysisSet &Destroyed, + Pass::AnalysisSet &Provided) { + if (Batcher == 0) // If we don't have a batcher yet, make one now. + Batcher = new BatcherClass(this); + // The Batcher will queue them passes up + MP->addToPassManager(Batcher, Destroyed, Provided); + } + + // closeBatcher - Terminate the batcher that is being worked on. + void closeBatcher() { + if (Batcher) { + Passes.push_back(Batcher); + Batcher = 0; + } + } +}; + + + +//===----------------------------------------------------------------------===// +// PassManagerTraits Specialization +// +// This pass manager is used to group together all of the BasicBlockPass's +// into a single unit. +// +template<> struct PassManagerTraits : public BasicBlockPass { + // PassClass - The type of passes tracked by this PassManager + typedef BasicBlockPass PassClass; + + // SubPassClass - The types of classes that should be collated together + // This is impossible to match, so BasicBlock instantiations of PassManagerT + // do not collate. + // + typedef PassManagerT SubPassClass; + + // BatcherClass - The type to use for collation of subtypes... This class is + // never instantiated for the PassManager, but it must be an + // instance of PassClass to typecheck. + // + typedef PassClass BatcherClass; + + // ParentClass - The type of the parent PassManager... + typedef PassManagerT ParentClass; + + // runPass - Specify how the pass should be run on the UnitType + static bool runPass(PassClass *P, BasicBlock *M) { + // todo, init and finalize + return P->runOnBasicBlock(M); + } + + // run - Implement the Pass interface... + virtual bool runOnBasicBlock(BasicBlock *BB); +}; + + + +//===----------------------------------------------------------------------===// +// PassManagerTraits Specialization +// +// This pass manager is used to group together all of the MethodPass's +// into a single unit. +// +template<> struct PassManagerTraits : public MethodPass { + // PassClass - The type of passes tracked by this PassManager + typedef MethodPass PassClass; + + // SubPassClass - The types of classes that should be collated together + typedef BasicBlockPass SubPassClass; + + // BatcherClass - The type to use for collation of subtypes... + typedef PassManagerT BatcherClass; + + // ParentClass - The type of the parent PassManager... + typedef PassManagerT ParentClass; + + // PMType - The type of the passmanager that subclasses this class + typedef PassManagerT PMType; + + // runPass - Specify how the pass should be run on the UnitType + static bool runPass(PassClass *P, Method *M) { + return P->runOnMethod(M); + } + + // Implement the MethodPass interface... + virtual bool doInitialization(Module *M); + virtual bool runOnMethod(Method *M); + virtual bool doFinalization(Module *M); +}; + + + +//===----------------------------------------------------------------------===// +// PassManagerTraits Specialization +// +// This is the top level PassManager implementation that holds generic passes. +// +template<> struct PassManagerTraits : public Pass { + // PassClass - The type of passes tracked by this PassManager + typedef Pass PassClass; + + // SubPassClass - The types of classes that should be collated together + typedef MethodPass SubPassClass; + + // BatcherClass - The type to use for collation of subtypes... + typedef PassManagerT BatcherClass; + + // ParentClass - The type of the parent PassManager... + typedef void ParentClass; + + // runPass - Specify how the pass should be run on the UnitType + static bool runPass(PassClass *P, Module *M) { return P->run(M); } + + // run - Implement the Pass interface... + virtual bool run(Module *M) { + return ((PassManagerT*)this)->runOnUnit(M); + } +}; + + + +//===----------------------------------------------------------------------===// +// PassManagerTraits Method Implementations +// + +// PassManagerTraits Implementations +// +inline bool PassManagerTraits::runOnBasicBlock(BasicBlock *BB) { + return ((PassManagerT*)this)->runOnUnit(BB); +} + + +// PassManagerTraits Implementations +// +inline bool PassManagerTraits::doInitialization(Module *M) { + bool Changed = false; + for (unsigned i = 0, e = ((PMType*)this)->Passes.size(); i != e; ++i) + ((PMType*)this)->Passes[i]->doInitialization(M); + return Changed; +} + +inline bool PassManagerTraits::runOnMethod(Method *M) { + return ((PMType*)this)->runOnUnit(M); +} + + +// PassManagerTraits Implementations +// +inline bool PassManagerTraits::doFinalization(Module *M) { + bool Changed = false; + for (unsigned i = 0, e = ((PMType*)this)->Passes.size(); i != e; ++i) + ((PMType*)this)->Passes[i]->doFinalization(M); + return Changed; +} + +#endif