mirror of
https://github.com/RPCSX/llvm.git
synced 2024-12-03 09:21:13 +00:00
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:
parent
f2a1dbc1e3
commit
aff5bcebb7
@ -3,30 +3,15 @@
|
|||||||
// This file defines a base class that indicates that a specified class is a
|
// This file defines a base class that indicates that a specified class is a
|
||||||
// transformation pass implementation.
|
// transformation pass implementation.
|
||||||
//
|
//
|
||||||
// Pass's are designed this way so that it is possible to apply N passes to a
|
// Pass's are designed this way so that it is possible to run passes in a cache
|
||||||
// module, by first doing N Pass specific initializations for the module, then
|
// and organizationally optimal order without having to specify it at the front
|
||||||
// looping over all of the methods in the module, doing method specific work
|
// end. This allows arbitrary passes to be strung together and have them
|
||||||
// N times for each method. Like this:
|
// executed as effeciently as possible.
|
||||||
//
|
//
|
||||||
// for_each(Passes.begin(), Passes.end(), doPassInitialization(Module));
|
// Passes should extend one of the classes below, depending on the guarantees
|
||||||
// for_each(Method *M <- Module->begin(), Module->end())
|
// that it can make about what will be modified as it is run. For example, most
|
||||||
// for_each(Passes.begin(), Passes.end(), doPerMethodWork(M));
|
// global optimizations should derive from MethodPass, because they do not add
|
||||||
//
|
// or delete methods, they operate on the internals of the method.
|
||||||
// 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.
|
|
||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
@ -36,91 +21,137 @@
|
|||||||
#include "llvm/Module.h"
|
#include "llvm/Module.h"
|
||||||
#include "llvm/Method.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 {
|
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
|
// Destructor - Virtual so we can be subclassed
|
||||||
inline virtual ~Pass() {}
|
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.
|
// 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
|
// runOnMethod - Virtual method overriden by subclasses to do the per-method
|
||||||
// per-method processing of the pass.
|
// 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.
|
// 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
|
#endif
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user