Implement a more powerful, simpler, pass system. This pass system can figure

out how to run a collection of passes optimially given their behaviors and
charactaristics.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@1506 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chris Lattner 2002-01-21 07:31:00 +00:00
parent f2a1dbc1e3
commit aff5bcebb7

View File

@ -3,30 +3,15 @@
// This file defines a base class that indicates that a specified class is a
// transformation pass implementation.
//
// Pass's are designed this way so that it is possible to apply N passes to a
// module, by first doing N Pass specific initializations for the module, then
// looping over all of the methods in the module, doing method specific work
// N times for each method. Like this:
// Pass's are designed this way so that it is possible to run passes in a cache
// and organizationally optimal order without having to specify it at the front
// end. This allows arbitrary passes to be strung together and have them
// executed as effeciently as possible.
//
// for_each(Passes.begin(), Passes.end(), doPassInitialization(Module));
// for_each(Method *M <- Module->begin(), Module->end())
// for_each(Passes.begin(), Passes.end(), doPerMethodWork(M));
//
// The other way to do things is like this:
// for_each(Pass *P <- Passes.begin(), Passes.end()) {
// Passes->doPassInitialization(Module)
// for_each(Module->begin(), Module->end(), P->doPerMethodWork);
// }
//
// But this can cause thrashing and poor cache performance, so we don't do it
// that way.
//
// Because a transformation does not see all methods consecutively, it should
// be careful about the state that it maintains... another pass may modify a
// method between two invocatations of doPerMethodWork.
//
// Also, implementations of doMethodWork should not remove any methods from the
// module.
// Passes should extend one of the classes below, depending on the guarantees
// that it can make about what will be modified as it is run. For example, most
// global optimizations should derive from MethodPass, because they do not add
// or delete methods, they operate on the internals of the method.
//
//===----------------------------------------------------------------------===//
@ -36,91 +21,137 @@
#include "llvm/Module.h"
#include "llvm/Method.h"
class MethodPassBatcher;
//===----------------------------------------------------------------------===//
// Pass interface - Implemented by all 'passes'.
// 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 {
//===--------------------------------------------------------------------===//
// The externally useful entry points
//
// runAllPasses - Run a bunch of passes on the specified module, efficiently.
static bool runAllPasses(Module *M, std::vector<Pass*> &Passes) {
bool MadeChanges = false;
// Run all of the pass initializers
for (unsigned i = 0; i < Passes.size(); ++i)
MadeChanges |= Passes[i]->doPassInitialization(M);
// Loop over all of the methods, applying all of the passes to them
for (unsigned m = 0; m < M->size(); ++m)
for (unsigned i = 0; i < Passes.size(); ++i)
MadeChanges |= Passes[i]->doPerMethodWork(*(M->begin()+m));
// Run all of the pass finalizers...
for (unsigned i = 0; i < Passes.size(); ++i)
MadeChanges |= Passes[i]->doPassFinalization(M);
return MadeChanges;
}
// runAllPassesAndFree - Run a bunch of passes on the specified module,
// efficiently. When done, delete all of the passes.
//
static bool runAllPassesAndFree(Module *M, std::vector<Pass*> &Passes) {
// First run all of the passes
bool MadeChanges = runAllPasses(M, Passes);
// Free all of the passes.
for (unsigned i = 0; i < Passes.size(); ++i)
delete Passes[i];
return MadeChanges;
}
// run(Module*) - Run this pass on a module and all of the methods contained
// within it. Returns true if any of the contained passes returned true.
//
bool run(Module *M) {
bool MadeChanges = doPassInitialization(M);
// Loop over methods in the module. doPerMethodWork could add a method to
// the Module, so we have to keep checking for end of method list condition.
//
for (unsigned m = 0; m < M->size(); ++m)
MadeChanges |= doPerMethodWork(*(M->begin()+m));
return MadeChanges | doPassFinalization(M);
}
// run(Method*) - Run this pass on a module and one specific method. Returns
// false on success.
//
bool run(Method *M) {
return doPassInitialization(M->getParent()) | doPerMethodWork(M) |
doPassFinalization(M->getParent());
}
//===--------------------------------------------------------------------===//
// Functions to be implemented by subclasses
//
// Destructor - Virtual so we can be subclassed
inline virtual ~Pass() {}
// doPassInitialization - Virtual method overridden by subclasses to do
virtual bool run(Module *M) = 0;
};
//===----------------------------------------------------------------------===//
// MethodPass class - This class is used to implement most global optimizations.
// Optimizations should subclass this class if they meet the following
// constraints:
// 1. Optimizations are organized globally, ie a method at a time
// 2. Optimizing a method does not cause the addition or removal of any methods
// in the module
//
struct MethodPass : public Pass {
// doInitialization - Virtual method overridden by subclasses to do
// any neccesary per-module initialization.
//
virtual bool doPassInitialization(Module *M) { return false; }
virtual bool doInitialization(Module *M) { return false; }
// doPerMethodWork - Virtual method overriden by subclasses to do the
// per-method processing of the pass.
// runOnMethod - Virtual method overriden by subclasses to do the per-method
// processing of the pass.
//
virtual bool doPerMethodWork(Method *M) { return false; }
virtual bool runOnMethod(Method *M) = 0;
// doPassFinalization - Virtual method overriden by subclasses to do any post
// doFinalization - Virtual method overriden by subclasses to do any post
// processing needed after all passes have run.
//
virtual bool doPassFinalization(Module *M) { return false; }
virtual bool doFinalization(Module *M) { return false; }
virtual bool run(Module *M) {
bool Changed = doInitialization(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());
}
};
//===----------------------------------------------------------------------===//
// 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
// meet the following constraints:
// 1. Optimizations are local, operating on either a basic block or
// 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.
//
struct BasicBlockPass : public CFGSafeMethodPass {
// 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;
}
bool run(BasicBlock *BB) {
Module *M = BB->getParent()->getParent();
return doInitialization(M) | runOnBasicBlock(BB) | doFinalization(M);
}
};
//===----------------------------------------------------------------------===//
// 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.
//
class PassManager {
std::vector<Pass*> Passes;
MethodPassBatcher *Batcher;
public:
PassManager() : Batcher(0) {}
~PassManager();
bool run(Module *M) {
bool MadeChanges = false;
// Run all of the pass initializers
for (unsigned i = 0, e = Passes.size(); i < e; ++i)
MadeChanges |= Passes[i]->run(M);
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(Pass *P);
void add(MethodPass *P);
void add(BasicBlockPass *P);
};
#endif