forked from OSchip/llvm-project
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. Convert code to use it. llvm-svn: 1507
This commit is contained in:
parent
e8d81d0819
commit
0686e435d1
|
@ -22,7 +22,7 @@
|
||||||
|
|
||||||
class PointerType;
|
class PointerType;
|
||||||
|
|
||||||
struct FindUnsafePointerTypes : public Pass {
|
struct FindUnsafePointerTypes : public MethodPass {
|
||||||
// UnsafeTypes - Set of types that are not safe to transform.
|
// UnsafeTypes - Set of types that are not safe to transform.
|
||||||
std::set<PointerType*> UnsafeTypes;
|
std::set<PointerType*> UnsafeTypes;
|
||||||
public:
|
public:
|
||||||
|
@ -32,11 +32,11 @@ public:
|
||||||
return UnsafeTypes;
|
return UnsafeTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
// doPerMethodWork - Inspect the operations that the specified method does on
|
// runOnMethod - Inspect the operations that the specified method does on
|
||||||
// values of various types. If they are deemed to be 'unsafe' note that the
|
// values of various types. If they are deemed to be 'unsafe' note that the
|
||||||
// type is not safe to transform.
|
// type is not safe to transform.
|
||||||
//
|
//
|
||||||
virtual bool doPerMethodWork(Method *M);
|
virtual bool runOnMethod(Method *M);
|
||||||
|
|
||||||
// printResults - Loop over the results of the analysis, printing out unsafe
|
// printResults - Loop over the results of the analysis, printing out unsafe
|
||||||
// types.
|
// types.
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
#include <set>
|
#include <set>
|
||||||
class SymbolTable;
|
class SymbolTable;
|
||||||
|
|
||||||
class FindUsedTypes : public Pass {
|
class FindUsedTypes : public MethodPass {
|
||||||
std::set<const Type *> UsedTypes;
|
std::set<const Type *> UsedTypes;
|
||||||
|
|
||||||
bool IncludeSymbolTables;
|
bool IncludeSymbolTables;
|
||||||
|
@ -45,14 +45,14 @@ private:
|
||||||
void IncorporateSymbolTable(const SymbolTable *ST);
|
void IncorporateSymbolTable(const SymbolTable *ST);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// doPassInitialization - This loops over global constants defined in the
|
// doInitialization - This loops over global constants defined in the
|
||||||
// module, converting them to their new type.
|
// module, converting them to their new type.
|
||||||
//
|
//
|
||||||
bool doPassInitialization(Module *M);
|
bool doInitialization(Module *M);
|
||||||
|
|
||||||
// doPerMethodWork - This incorporates all types used by the specified method
|
// runOnMethod - This incorporates all types used by the specified method
|
||||||
//
|
//
|
||||||
bool doPerMethodWork(Method *M);
|
bool runOnMethod(Method *M);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
//===- llvm/Assembly/PrintModulePass.h - Printing Pass -----------*- C++ -*--=//
|
//===- llvm/Assembly/PrintModulePass.h - Printing Pass -----------*- C++ -*--=//
|
||||||
//
|
//
|
||||||
// This file defines a simple pass to print out methods of a module as they are
|
// This file defines two passes to print out a module. The PrintModulePass
|
||||||
// processed.
|
// pass simply prints out the entire module when it is executed. The
|
||||||
|
// PrintMethodPass class is designed to be pipelined with other MethodPass's,
|
||||||
|
// and prints out the methods of the class as they are processed.
|
||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
@ -13,36 +15,42 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
class PrintModulePass : public Pass {
|
class PrintModulePass : public Pass {
|
||||||
std::string Banner; // String to print before each method
|
|
||||||
std::ostream *Out; // ostream to print on
|
std::ostream *Out; // ostream to print on
|
||||||
bool DeleteStream; // Delete the ostream in our dtor?
|
bool DeleteStream; // Delete the ostream in our dtor?
|
||||||
bool PrintPerMethod; // Print one method at a time rather than the whole?
|
|
||||||
public:
|
public:
|
||||||
inline PrintModulePass(const std::string &B, std::ostream *o = &std::cout,
|
inline PrintModulePass(std::ostream *o = &std::cout, bool DS = false)
|
||||||
bool DS = false,
|
: Out(o), DeleteStream(DS) {
|
||||||
bool printPerMethod = true)
|
|
||||||
: Banner(B), Out(o), DeleteStream(DS), PrintPerMethod(printPerMethod) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline ~PrintModulePass() {
|
inline ~PrintModulePass() {
|
||||||
if (DeleteStream) delete Out;
|
if (DeleteStream) delete Out;
|
||||||
}
|
}
|
||||||
|
|
||||||
// doPerMethodWork - This pass just prints a banner followed by the method as
|
bool run(Module *M) {
|
||||||
// it's processed.
|
(*Out) << M;
|
||||||
//
|
|
||||||
bool doPerMethodWork(Method *M) {
|
|
||||||
if (PrintPerMethod)
|
|
||||||
(*Out) << Banner << M;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// doPassFinalization - Virtual method overriden by subclasses to do any post
|
class PrintMethodPass : public MethodPass {
|
||||||
// processing needed after all passes have run.
|
std::string Banner; // String to print before each method
|
||||||
|
std::ostream *Out; // ostream to print on
|
||||||
|
bool DeleteStream; // Delete the ostream in our dtor?
|
||||||
|
public:
|
||||||
|
inline PrintMethodPass(const std::string &B, std::ostream *o = &std::cout,
|
||||||
|
bool DS = false)
|
||||||
|
: Banner(B), Out(o), DeleteStream(DS) {
|
||||||
|
}
|
||||||
|
|
||||||
|
inline ~PrintMethodPass() {
|
||||||
|
if (DeleteStream) delete Out;
|
||||||
|
}
|
||||||
|
|
||||||
|
// runOnMethod - This pass just prints a banner followed by the method as
|
||||||
|
// it's processed.
|
||||||
//
|
//
|
||||||
bool doPassFinalization(Module *M) {
|
bool runOnMethod(Method *M) {
|
||||||
if (! PrintPerMethod)
|
(*Out) << Banner << M;
|
||||||
(*Out) << Banner << M;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -23,7 +23,7 @@ public:
|
||||||
if (DeleteStream) delete Out;
|
if (DeleteStream) delete Out;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool doPassFinalization(Module *M) {
|
bool run(Module *M) {
|
||||||
WriteBytecodeToFile(M, *Out);
|
WriteBytecodeToFile(M, *Out);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
#include "llvm/Pass.h"
|
#include "llvm/Pass.h"
|
||||||
class TargetData;
|
class TargetData;
|
||||||
|
|
||||||
class LowerAllocations : public Pass {
|
class LowerAllocations : public MethodPass {
|
||||||
Method *MallocMeth; // Methods in the module we are processing
|
Method *MallocMeth; // Methods in the module we are processing
|
||||||
Method *FreeMeth; // Initialized by doPassInitializationVirt
|
Method *FreeMeth; // Initialized by doPassInitializationVirt
|
||||||
|
|
||||||
|
@ -28,12 +28,12 @@ public:
|
||||||
//
|
//
|
||||||
// This function is always successful.
|
// This function is always successful.
|
||||||
//
|
//
|
||||||
bool doPassInitialization(Module *M);
|
bool doInitialization(Module *M);
|
||||||
|
|
||||||
// doPerMethodWork - This method does the actual work of converting
|
// doPerMethodWork - This method does the actual work of converting
|
||||||
// instructions over, assuming that the pass has already been initialized.
|
// instructions over, assuming that the pass has already been initialized.
|
||||||
//
|
//
|
||||||
bool doPerMethodWork(Method *M);
|
bool runOnMethod(Method *M);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -13,13 +13,13 @@ class CallInst;
|
||||||
|
|
||||||
namespace opt {
|
namespace opt {
|
||||||
|
|
||||||
struct MethodInlining : public Pass {
|
struct MethodInlining : public MethodPass {
|
||||||
// DoMethodInlining - Use a heuristic based approach to inline methods that
|
// DoMethodInlining - Use a heuristic based approach to inline methods that
|
||||||
// seem to look good.
|
// seem to look good.
|
||||||
//
|
//
|
||||||
static bool doMethodInlining(Method *M);
|
static bool doMethodInlining(Method *M);
|
||||||
|
|
||||||
virtual bool doPerMethodWork(Method *M) {
|
virtual bool runOnMethod(Method *M) {
|
||||||
return doMethodInlining(M);
|
return doMethodInlining(M);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -11,12 +11,12 @@
|
||||||
|
|
||||||
#include "llvm/Pass.h"
|
#include "llvm/Pass.h"
|
||||||
|
|
||||||
struct HoistPHIConstants : public Pass {
|
struct HoistPHIConstants : public MethodPass {
|
||||||
// doHoistPHIConstants - Hoist constants out of PHI instructions
|
// doHoistPHIConstants - Hoist constants out of PHI instructions
|
||||||
//
|
//
|
||||||
static bool doHoistPHIConstants(Method *M);
|
static bool doHoistPHIConstants(Method *M);
|
||||||
|
|
||||||
virtual bool doPerMethodWork(Method *M) { return doHoistPHIConstants(M); }
|
virtual bool runOnMethod(Method *M) { return doHoistPHIConstants(M); }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
#include "llvm/Analysis/FindUsedTypes.h"
|
#include "llvm/Analysis/FindUsedTypes.h"
|
||||||
|
|
||||||
class CleanupGCCOutput : public Pass {
|
class CleanupGCCOutput : public MethodPass {
|
||||||
Method *Malloc, *Free; // Pointers to external declarations, or null if none
|
Method *Malloc, *Free; // Pointers to external declarations, or null if none
|
||||||
FindUsedTypes FUT; // Use FUT to eliminate type names that are never used
|
FindUsedTypes FUT; // Use FUT to eliminate type names that are never used
|
||||||
public:
|
public:
|
||||||
|
@ -27,14 +27,14 @@ public:
|
||||||
//
|
//
|
||||||
// Also, initialize instance variables.
|
// Also, initialize instance variables.
|
||||||
//
|
//
|
||||||
bool doPassInitialization(Module *M);
|
bool doInitialization(Module *M);
|
||||||
|
|
||||||
// doPerMethodWork - This method simplifies the specified method hopefully.
|
// doPerMethodWork - This method simplifies the specified method hopefully.
|
||||||
//
|
//
|
||||||
bool doPerMethodWork(Method *M);
|
bool runOnMethod(Method *M);
|
||||||
|
|
||||||
// doPassFinalization - Strip out type names that are unused by the program
|
// doPassFinalization - Strip out type names that are unused by the program
|
||||||
bool doPassFinalization(Module *M);
|
bool doFinalization(Module *M);
|
||||||
private:
|
private:
|
||||||
bool doOneCleanupPass(Method *M);
|
bool doOneCleanupPass(Method *M);
|
||||||
};
|
};
|
||||||
|
|
|
@ -22,7 +22,8 @@
|
||||||
class Constant;
|
class Constant;
|
||||||
class GlobalVariable;
|
class GlobalVariable;
|
||||||
|
|
||||||
class ConstantMerge : public Pass {
|
// FIXME: ConstantMerge should not be a methodPass!!!
|
||||||
|
class ConstantMerge : public MethodPass {
|
||||||
protected:
|
protected:
|
||||||
std::map<Constant*, GlobalVariable*> Constants;
|
std::map<Constant*, GlobalVariable*> Constants;
|
||||||
unsigned LastConstantSeen;
|
unsigned LastConstantSeen;
|
||||||
|
@ -34,14 +35,16 @@ public:
|
||||||
//
|
//
|
||||||
static bool mergeDuplicateConstants(Module *M);
|
static bool mergeDuplicateConstants(Module *M);
|
||||||
|
|
||||||
// doPassInitialization - For this pass, process all of the globals in the
|
// doInitialization - For this pass, process all of the globals in the
|
||||||
// module, eliminating duplicate constants.
|
// module, eliminating duplicate constants.
|
||||||
//
|
//
|
||||||
bool doPassInitialization(Module *M);
|
bool doInitialization(Module *M);
|
||||||
|
|
||||||
// doPassFinalization - Clean up internal state for this module
|
bool runOnMethod(Method*) { return false; }
|
||||||
|
|
||||||
|
// doFinalization - Clean up internal state for this module
|
||||||
//
|
//
|
||||||
bool doPassFinalization(Module *M) {
|
bool doFinalization(Module *M) {
|
||||||
LastConstantSeen = 0;
|
LastConstantSeen = 0;
|
||||||
Constants.clear();
|
Constants.clear();
|
||||||
return false;
|
return false;
|
||||||
|
@ -52,7 +55,7 @@ struct DynamicConstantMerge : public ConstantMerge {
|
||||||
// doPerMethodWork - Check to see if any globals have been added to the
|
// doPerMethodWork - Check to see if any globals have been added to the
|
||||||
// global list for the module. If so, eliminate them.
|
// global list for the module. If so, eliminate them.
|
||||||
//
|
//
|
||||||
bool doPerMethodWork(Method *M);
|
bool runOnMethod(Method *M);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -7,15 +7,17 @@
|
||||||
#ifndef LLVM_TRANSFORM_IPO_GLOBALDCE_H
|
#ifndef LLVM_TRANSFORM_IPO_GLOBALDCE_H
|
||||||
#define LLVM_TRANSFORM_IPO_GLOBALDCE_H
|
#define LLVM_TRANSFORM_IPO_GLOBALDCE_H
|
||||||
|
|
||||||
|
#include "llvm/Pass.h"
|
||||||
|
|
||||||
namespace cfg { class CallGraph; }
|
namespace cfg { class CallGraph; }
|
||||||
class Module;
|
class Module;
|
||||||
|
|
||||||
struct GlobalDCE {
|
struct GlobalDCE : public Pass {
|
||||||
|
|
||||||
// run - Do the GlobalDCE pass on the specified module, optionally updating
|
// run - Do the GlobalDCE pass on the specified module, optionally updating
|
||||||
// the specified callgraph to reflect the changes.
|
// the specified callgraph to reflect the changes.
|
||||||
//
|
//
|
||||||
bool run(Module *M, cfg::CallGraph *CG = 0);
|
bool run(Module *M);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,22 +1,27 @@
|
||||||
//===- llvm/Transforms/SwapStructContents.h - Permute Structs ----*- C++ -*--=//
|
//===- llvm/Transforms/SimpleStructMutation.h - Permute Structs --*- C++ -*--=//
|
||||||
//
|
//
|
||||||
// This pass does a simple transformation that swaps all of the elements of the
|
// This pass does is a wrapper that can do a few simple structure mutation
|
||||||
// struct types in the program around.
|
// transformations.
|
||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#ifndef LLVM_TRANSFORMS_SWAPSTRUCTCONTENTS_H
|
#ifndef LLVM_TRANSFORMS_SIMPLESTRUCTMUTATION_H
|
||||||
#define LLVM_TRANSFORMS_SWAPSTRUCTCONTENTS_H
|
#define LLVM_TRANSFORMS_SIMPLESTRUCTMUTATION_H
|
||||||
|
|
||||||
#include "llvm/Transforms/MutateStructTypes.h"
|
#include "llvm/Transforms/MutateStructTypes.h"
|
||||||
|
|
||||||
// FIXME: Move to correct location!
|
class SimpleStructMutation : public MutateStructTypes {
|
||||||
class PrebuiltStructMutation : public MutateStructTypes {
|
|
||||||
public:
|
public:
|
||||||
enum Transform { SwapElements, SortElements };
|
enum Transform { SwapElements, SortElements } CurrentXForm;
|
||||||
|
|
||||||
PrebuiltStructMutation(Module *M, enum Transform XForm)
|
SimpleStructMutation(enum Transform XForm) : CurrentXForm(XForm) {}
|
||||||
: MutateStructTypes(getTransforms(M, XForm)) {}
|
|
||||||
|
virtual bool run(Module *M) {
|
||||||
|
setTransforms(getTransforms(M, CurrentXForm));
|
||||||
|
bool Changed = MutateStructTypes::run(M);
|
||||||
|
clearTransforms();
|
||||||
|
return Changed;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static TransformsType getTransforms(Module *M, enum Transform);
|
static TransformsType getTransforms(Module *M, enum Transform);
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
#include "llvm/Pass.h"
|
#include "llvm/Pass.h"
|
||||||
class Method;
|
class Method;
|
||||||
|
|
||||||
class InsertTraceCode : public Pass {
|
class InsertTraceCode : public MethodPass {
|
||||||
bool TraceBasicBlockExits, TraceMethodExits;
|
bool TraceBasicBlockExits, TraceMethodExits;
|
||||||
Method *PrintfMeth;
|
Method *PrintfMeth;
|
||||||
public:
|
public:
|
||||||
|
@ -21,7 +21,7 @@ public:
|
||||||
|
|
||||||
// Add a prototype for printf if it is not already in the program.
|
// Add a prototype for printf if it is not already in the program.
|
||||||
//
|
//
|
||||||
bool doPassInitialization(Module *M);
|
bool doInitialization(Module *M);
|
||||||
|
|
||||||
//--------------------------------------------------------------------------
|
//--------------------------------------------------------------------------
|
||||||
// Function InsertCodeToTraceValues
|
// Function InsertCodeToTraceValues
|
||||||
|
@ -32,9 +32,9 @@ public:
|
||||||
static bool doit(Method *M, bool traceBasicBlockExits,
|
static bool doit(Method *M, bool traceBasicBlockExits,
|
||||||
bool traceMethodExits, Method *Printf);
|
bool traceMethodExits, Method *Printf);
|
||||||
|
|
||||||
// doPerMethodWork - This method does the work. Always successful.
|
// runOnMethod - This method does the work. Always successful.
|
||||||
//
|
//
|
||||||
bool doPerMethodWork(Method *M) {
|
bool runOnMethod(Method *M) {
|
||||||
return doit(M, TraceBasicBlockExits, TraceMethodExits, PrintfMeth);
|
return doit(M, TraceBasicBlockExits, TraceMethodExits, PrintfMeth);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -51,25 +51,40 @@ public:
|
||||||
//
|
//
|
||||||
typedef std::map<const StructType*, std::vector<int> > TransformsType;
|
typedef std::map<const StructType*, std::vector<int> > TransformsType;
|
||||||
|
|
||||||
MutateStructTypes(const TransformsType &Transforms);
|
MutateStructTypes(const TransformsType &Transforms) {
|
||||||
|
setTransforms(Transforms);
|
||||||
|
}
|
||||||
|
|
||||||
|
// run - do the transformation
|
||||||
|
virtual bool run(Module *M);
|
||||||
|
|
||||||
// doPassInitialization - This loops over global constants defined in the
|
protected:
|
||||||
|
|
||||||
|
// Alternatively, it is valid to subclass this class and provide transforms
|
||||||
|
// this way. See SimpleStructMutation for an example.
|
||||||
|
//
|
||||||
|
MutateStructTypes() {}
|
||||||
|
void setTransforms(const TransformsType &Transforms);
|
||||||
|
void clearTransforms();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
// processGlobals - This loops over global constants defined in the
|
||||||
// module, converting them to their new type. Also this creates placeholder
|
// module, converting them to their new type. Also this creates placeholder
|
||||||
// methods for methods than need to be copied because they have a new
|
// methods for methods than need to be copied because they have a new
|
||||||
// signature type.
|
// signature type.
|
||||||
//
|
//
|
||||||
bool doPassInitialization(Module *M);
|
void processGlobals(Module *M);
|
||||||
|
|
||||||
// doPerMethodWork - This transforms the instructions of the method to use the
|
// transformMethod - This transforms the instructions of the method to use the
|
||||||
// new types.
|
// new types.
|
||||||
//
|
//
|
||||||
bool doPerMethodWork(Method *M);
|
void transformMethod(Method *M);
|
||||||
|
|
||||||
// doPassFinalization - This removes the old versions of methods that are no
|
// removeDeadGlobals - This removes the old versions of methods that are no
|
||||||
// longer needed.
|
// longer needed.
|
||||||
//
|
//
|
||||||
virtual bool doPassFinalization(Module *M);
|
void removeDeadGlobals(Module *M);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// ConvertType - Convert from the old type system to the new one...
|
// ConvertType - Convert from the old type system to the new one...
|
||||||
|
|
|
@ -15,10 +15,10 @@
|
||||||
// expressions as possible, by converting expressions to use getelementptr and
|
// expressions as possible, by converting expressions to use getelementptr and
|
||||||
// friends.
|
// friends.
|
||||||
//
|
//
|
||||||
struct RaisePointerReferences : public Pass {
|
struct RaisePointerReferences : public MethodPass {
|
||||||
static bool doit(Method *M);
|
static bool doit(Method *M);
|
||||||
|
|
||||||
virtual bool doPerMethodWork(Method *M) { return doit(M); }
|
virtual bool runOnMethod(Method *M) { return doit(M); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -26,10 +26,10 @@ struct RaisePointerReferences : public Pass {
|
||||||
// converts all induction variables to reference a cannonical induction
|
// converts all induction variables to reference a cannonical induction
|
||||||
// variable (which starts at 0 and counts by 1).
|
// variable (which starts at 0 and counts by 1).
|
||||||
//
|
//
|
||||||
struct EliminateAuxillaryInductionVariables : public Pass {
|
struct EliminateAuxillaryInductionVariables : public MethodPass {
|
||||||
static bool doit(Method *M) { return false; } // TODO!
|
static bool doit(Method *M) { return false; } // TODO!
|
||||||
|
|
||||||
virtual bool doPerMethodWork(Method *M) { return doit(M); }
|
virtual bool runOnMethod(Method *M) { return doit(M); }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -12,7 +12,7 @@ class TerminatorInst;
|
||||||
|
|
||||||
namespace opt {
|
namespace opt {
|
||||||
|
|
||||||
struct ConstantPropogation : public Pass {
|
struct ConstantPropogation : public MethodPass {
|
||||||
// doConstantPropogation - Do trivial constant propogation and expression
|
// doConstantPropogation - Do trivial constant propogation and expression
|
||||||
// folding
|
// folding
|
||||||
static bool doConstantPropogation(Method *M);
|
static bool doConstantPropogation(Method *M);
|
||||||
|
@ -22,7 +22,7 @@ struct ConstantPropogation : public Pass {
|
||||||
//
|
//
|
||||||
static bool doConstantPropogation(BasicBlock *BB, BasicBlock::iterator &I);
|
static bool doConstantPropogation(BasicBlock *BB, BasicBlock::iterator &I);
|
||||||
|
|
||||||
inline bool doPerMethodWork(Method *M) {
|
inline bool runOnMethod(Method *M) {
|
||||||
return doConstantPropogation(M);
|
return doConstantPropogation(M);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -39,10 +39,10 @@ bool ConstantFoldTerminator(TerminatorInst *T);
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// Sparse Conditional Constant Propogation Pass
|
// Sparse Conditional Constant Propogation Pass
|
||||||
//
|
//
|
||||||
struct SCCPPass : public Pass {
|
struct SCCPPass : public MethodPass {
|
||||||
static bool doSCCP(Method *M);
|
static bool doSCCP(Method *M);
|
||||||
|
|
||||||
inline bool doPerMethodWork(Method *M) {
|
inline bool runOnMethod(Method *M) {
|
||||||
return doSCCP(M);
|
return doSCCP(M);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
|
|
||||||
namespace opt {
|
namespace opt {
|
||||||
|
|
||||||
struct DeadCodeElimination : public Pass {
|
struct DeadCodeElimination : public MethodPass {
|
||||||
// External Interface:
|
// External Interface:
|
||||||
//
|
//
|
||||||
static bool doDCE(Method *M);
|
static bool doDCE(Method *M);
|
||||||
|
@ -33,23 +33,23 @@ struct DeadCodeElimination : public Pass {
|
||||||
static bool RemoveUnusedGlobalValues(Module *M);
|
static bool RemoveUnusedGlobalValues(Module *M);
|
||||||
|
|
||||||
// Pass Interface...
|
// Pass Interface...
|
||||||
virtual bool doPassInitialization(Module *M) {
|
virtual bool doInitialization(Module *M) {
|
||||||
return RemoveUnusedGlobalValues(M);
|
return RemoveUnusedGlobalValues(M);
|
||||||
}
|
}
|
||||||
virtual bool doPerMethodWork(Method *M) { return doDCE(M); }
|
virtual bool runOnMethod(Method *M) { return doDCE(M); }
|
||||||
virtual bool doPassFinalization(Module *M) {
|
virtual bool doFinalization(Module *M) {
|
||||||
return RemoveUnusedGlobalValues(M);
|
return RemoveUnusedGlobalValues(M);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct AgressiveDCE : public Pass {
|
struct AgressiveDCE : public MethodPass {
|
||||||
// DoADCE - Execute the Agressive Dead Code Elimination Algorithm
|
// DoADCE - Execute the Agressive Dead Code Elimination Algorithm
|
||||||
//
|
//
|
||||||
static bool doADCE(Method *M); // Defined in ADCE.cpp
|
static bool doADCE(Method *M); // Defined in ADCE.cpp
|
||||||
|
|
||||||
virtual bool doPerMethodWork(Method *M) {
|
virtual bool runOnMethod(Method *M) {
|
||||||
return doADCE(M);
|
return doADCE(M);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -10,10 +10,10 @@
|
||||||
|
|
||||||
#include "llvm/Pass.h"
|
#include "llvm/Pass.h"
|
||||||
|
|
||||||
struct InductionVariableSimplify : public Pass {
|
struct InductionVariableSimplify : public MethodPass {
|
||||||
static bool doit(Method *M);
|
static bool doit(Method *M);
|
||||||
|
|
||||||
virtual bool doPerMethodWork(Method *M) { return doit(M); }
|
virtual bool runOnMethod(Method *M) { return doit(M); }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -12,12 +12,12 @@
|
||||||
|
|
||||||
namespace opt {
|
namespace opt {
|
||||||
|
|
||||||
struct InductionVariableCannonicalize : public Pass {
|
struct InductionVariableCannonicalize : public MethodPass {
|
||||||
// doInductionVariableCannonicalize - Simplify induction variables in loops
|
// doInductionVariableCannonicalize - Simplify induction variables in loops
|
||||||
//
|
//
|
||||||
static bool doIt(Method *M);
|
static bool doIt(Method *M);
|
||||||
|
|
||||||
virtual bool doPerMethodWork(Method *M) {
|
virtual bool runOnMethod(Method *M) {
|
||||||
return doIt(M);
|
return doIt(M);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -17,11 +17,11 @@
|
||||||
|
|
||||||
#include "llvm/Pass.h"
|
#include "llvm/Pass.h"
|
||||||
|
|
||||||
struct InstructionCombining : public Pass {
|
struct InstructionCombining : public MethodPass {
|
||||||
static bool doit(Method *M);
|
static bool doit(Method *M);
|
||||||
static bool CombineInstruction(Instruction *I);
|
static bool CombineInstruction(Instruction *I);
|
||||||
|
|
||||||
virtual bool doPerMethodWork(Method *M) { return doit(M); }
|
virtual bool runOnMethod(Method *M) { return doit(M); }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -12,28 +12,28 @@
|
||||||
|
|
||||||
namespace opt {
|
namespace opt {
|
||||||
|
|
||||||
struct SymbolStripping : public Pass {
|
struct SymbolStripping : public MethodPass {
|
||||||
// doSymbolStripping - Remove all symbolic information from a method
|
// doSymbolStripping - Remove all symbolic information from a method
|
||||||
//
|
//
|
||||||
static bool doSymbolStripping(Method *M);
|
static bool doSymbolStripping(Method *M);
|
||||||
|
|
||||||
virtual bool doPerMethodWork(Method *M) {
|
virtual bool runOnMethod(Method *M) {
|
||||||
return doSymbolStripping(M);
|
return doSymbolStripping(M);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FullSymbolStripping : public Pass {
|
struct FullSymbolStripping : public MethodPass {
|
||||||
|
|
||||||
// doStripGlobalSymbols - Remove all symbolic information from all methods
|
// doStripGlobalSymbols - Remove all symbolic information from all methods
|
||||||
// in a module, and all module level symbols. (method names, etc...)
|
// in a module, and all module level symbols. (method names, etc...)
|
||||||
//
|
//
|
||||||
static bool doStripGlobalSymbols(Module *M);
|
static bool doStripGlobalSymbols(Module *M);
|
||||||
|
|
||||||
virtual bool doPassInitialization(Module *M) {
|
virtual bool doInitialization(Module *M) {
|
||||||
return doStripGlobalSymbols(M);
|
return doStripGlobalSymbols(M);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool doPerMethodWork(Method *M) {
|
virtual bool runOnMethod(Method *M) {
|
||||||
return SymbolStripping::doSymbolStripping(M);
|
return SymbolStripping::doSymbolStripping(M);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -45,11 +45,11 @@ static inline bool isSafeInstruction(const Instruction *I) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// doPerMethodWork - Inspect the operations that the specified method does on
|
// runOnMethod - Inspect the operations that the specified method does on
|
||||||
// values of various types. If they are deemed to be 'unsafe' note that the
|
// values of various types. If they are deemed to be 'unsafe' note that the
|
||||||
// type is not safe to transform.
|
// type is not safe to transform.
|
||||||
//
|
//
|
||||||
bool FindUnsafePointerTypes::doPerMethodWork(Method *Meth) {
|
bool FindUnsafePointerTypes::runOnMethod(Method *Meth) {
|
||||||
const Method *M = Meth; // We don't need/want write access
|
const Method *M = Meth; // We don't need/want write access
|
||||||
for (Method::const_inst_iterator I = M->inst_begin(), E = M->inst_end();
|
for (Method::const_inst_iterator I = M->inst_begin(), E = M->inst_end();
|
||||||
I != E; ++I) {
|
I != E; ++I) {
|
||||||
|
|
|
@ -35,10 +35,10 @@ void FindUsedTypes::IncorporateSymbolTable(const SymbolTable *ST) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// doPassInitialization - This loops over global constants defined in the
|
// doInitialization - This loops over global constants defined in the
|
||||||
// module, converting them to their new type.
|
// module, converting them to their new type.
|
||||||
//
|
//
|
||||||
bool FindUsedTypes::doPassInitialization(Module *m) {
|
bool FindUsedTypes::doInitialization(Module *m) {
|
||||||
const Module *M = m;
|
const Module *M = m;
|
||||||
if (IncludeSymbolTables && M->hasSymbolTable())
|
if (IncludeSymbolTables && M->hasSymbolTable())
|
||||||
IncorporateSymbolTable(M->getSymbolTable()); // Add symtab first...
|
IncorporateSymbolTable(M->getSymbolTable()); // Add symtab first...
|
||||||
|
@ -51,7 +51,7 @@ bool FindUsedTypes::doPassInitialization(Module *m) {
|
||||||
|
|
||||||
// doPerMethodWork - This incorporates all types used by the specified method
|
// doPerMethodWork - This incorporates all types used by the specified method
|
||||||
//
|
//
|
||||||
bool FindUsedTypes::doPerMethodWork(Method *m) {
|
bool FindUsedTypes::runOnMethod(Method *m) {
|
||||||
const Method *M = m;
|
const Method *M = m;
|
||||||
if (IncludeSymbolTables && M->hasSymbolTable())
|
if (IncludeSymbolTables && M->hasSymbolTable())
|
||||||
IncorporateSymbolTable(M->getSymbolTable()); // Add symtab first...
|
IncorporateSymbolTable(M->getSymbolTable()); // Add symtab first...
|
||||||
|
|
|
@ -65,16 +65,16 @@ bool ConstantMerge::mergeDuplicateConstants(Module *M) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// doPassInitialization - For this pass, process all of the globals in the
|
// doInitialization - For this pass, process all of the globals in the
|
||||||
// module, eliminating duplicate constants.
|
// module, eliminating duplicate constants.
|
||||||
//
|
//
|
||||||
bool ConstantMerge::doPassInitialization(Module *M) {
|
bool ConstantMerge::doInitialization(Module *M) {
|
||||||
return ::mergeDuplicateConstants(M, LastConstantSeen, Constants);
|
return ::mergeDuplicateConstants(M, LastConstantSeen, Constants);
|
||||||
}
|
}
|
||||||
|
|
||||||
// doPerMethodWork - Check to see if any globals have been added to the
|
// doPerMethodWork - Check to see if any globals have been added to the
|
||||||
// global list for the module. If so, eliminate them.
|
// global list for the module. If so, eliminate them.
|
||||||
//
|
//
|
||||||
bool DynamicConstantMerge::doPerMethodWork(Method *M) {
|
bool DynamicConstantMerge::runOnMethod(Method *M) {
|
||||||
return ::mergeDuplicateConstants(M->getParent(), LastConstantSeen, Constants);
|
return ::mergeDuplicateConstants(M->getParent(), LastConstantSeen, Constants);
|
||||||
}
|
}
|
||||||
|
|
|
@ -220,14 +220,14 @@ static inline bool ShouldNukeSymtabEntry(const std::pair<string, Value*> &E) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// doPassInitialization - For this pass, it removes global symbol table
|
// doInitialization - For this pass, it removes global symbol table
|
||||||
// entries for primitive types. These are never used for linking in GCC and
|
// entries for primitive types. These are never used for linking in GCC and
|
||||||
// they make the output uglier to look at, so we nuke them.
|
// they make the output uglier to look at, so we nuke them.
|
||||||
//
|
//
|
||||||
bool CleanupGCCOutput::doPassInitialization(Module *M) {
|
bool CleanupGCCOutput::doInitialization(Module *M) {
|
||||||
bool Changed = false;
|
bool Changed = false;
|
||||||
|
|
||||||
FUT.doPassInitialization(M);
|
FUT.doInitialization(M);
|
||||||
|
|
||||||
if (PtrSByte == 0)
|
if (PtrSByte == 0)
|
||||||
PtrSByte = PointerType::get(Type::SByteTy);
|
PtrSByte = PointerType::get(Type::SByteTy);
|
||||||
|
@ -551,17 +551,17 @@ static bool fixLocalProblems(Method *M) {
|
||||||
|
|
||||||
// doPerMethodWork - This method simplifies the specified method hopefully.
|
// doPerMethodWork - This method simplifies the specified method hopefully.
|
||||||
//
|
//
|
||||||
bool CleanupGCCOutput::doPerMethodWork(Method *M) {
|
bool CleanupGCCOutput::runOnMethod(Method *M) {
|
||||||
bool Changed = fixLocalProblems(M);
|
bool Changed = fixLocalProblems(M);
|
||||||
while (doOneCleanupPass(M)) Changed = true;
|
while (doOneCleanupPass(M)) Changed = true;
|
||||||
|
|
||||||
FUT.doPerMethodWork(M);
|
FUT.runOnMethod(M);
|
||||||
return Changed;
|
return Changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CleanupGCCOutput::doPassFinalization(Module *M) {
|
bool CleanupGCCOutput::doFinalization(Module *M) {
|
||||||
bool Changed = false;
|
bool Changed = false;
|
||||||
FUT.doPassFinalization(M);
|
FUT.doFinalization(M);
|
||||||
|
|
||||||
if (M->hasSymbolTable()) {
|
if (M->hasSymbolTable()) {
|
||||||
SymbolTable *ST = M->getSymbolTable();
|
SymbolTable *ST = M->getSymbolTable();
|
||||||
|
|
|
@ -11,10 +11,7 @@
|
||||||
#include "Support/DepthFirstIterator.h"
|
#include "Support/DepthFirstIterator.h"
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
static bool RemoveUnreachableMethods(Module *M, cfg::CallGraph *CG) {
|
static bool RemoveUnreachableMethods(Module *M, cfg::CallGraph &CallGraph) {
|
||||||
// Create a call graph if one is not already available...
|
|
||||||
cfg::CallGraph &CallGraph = CG ? *CG : *new cfg::CallGraph(M);
|
|
||||||
|
|
||||||
// Calculate which methods are reachable from the external methods in the call
|
// Calculate which methods are reachable from the external methods in the call
|
||||||
// graph.
|
// graph.
|
||||||
//
|
//
|
||||||
|
@ -36,11 +33,7 @@ static bool RemoveUnreachableMethods(Module *M, cfg::CallGraph *CG) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Nothing to do if no unreachable methods have been found...
|
// Nothing to do if no unreachable methods have been found...
|
||||||
if (MethodsToDelete.empty()) {
|
if (MethodsToDelete.empty()) return false;
|
||||||
// Free the created call graph if it was not passed in
|
|
||||||
if (&CallGraph != CG) delete &CallGraph;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unreachables methods have been found and should have no references to them,
|
// Unreachables methods have been found and should have no references to them,
|
||||||
// delete them now.
|
// delete them now.
|
||||||
|
@ -49,11 +42,12 @@ static bool RemoveUnreachableMethods(Module *M, cfg::CallGraph *CG) {
|
||||||
E = MethodsToDelete.end(); I != E; ++I)
|
E = MethodsToDelete.end(); I != E; ++I)
|
||||||
delete CallGraph.removeMethodFromModule(*I);
|
delete CallGraph.removeMethodFromModule(*I);
|
||||||
|
|
||||||
// Free the created call graph if it was not passed in
|
|
||||||
if (&CallGraph != CG) delete &CallGraph;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GlobalDCE::run(Module *M, cfg::CallGraph *CG = 0) {
|
bool GlobalDCE::run(Module *M) {
|
||||||
return RemoveUnreachableMethods(M, CG);
|
// TODO: FIXME: GET THE CALL GRAPH FROM THE PASS!
|
||||||
|
// Create a call graph if one is not already available...
|
||||||
|
cfg::CallGraph CallGraph(M);
|
||||||
|
return RemoveUnreachableMethods(M, CallGraph);
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,9 +20,9 @@
|
||||||
#include "llvm/iMemory.h"
|
#include "llvm/iMemory.h"
|
||||||
#include "llvm/iTerminators.h"
|
#include "llvm/iTerminators.h"
|
||||||
#include "llvm/iOther.h"
|
#include "llvm/iOther.h"
|
||||||
|
#include "Support/STLExtras.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
using std::map;
|
using std::map;
|
||||||
using std::make_pair;
|
|
||||||
using std::vector;
|
using std::vector;
|
||||||
|
|
||||||
// To enable debugging, uncomment this...
|
// To enable debugging, uncomment this...
|
||||||
|
@ -56,7 +56,7 @@ const Type *MutateStructTypes::ConvertType(const Type *Ty) {
|
||||||
const Type *DestTy = 0;
|
const Type *DestTy = 0;
|
||||||
|
|
||||||
PATypeHolder<Type> PlaceHolder = OpaqueType::get();
|
PATypeHolder<Type> PlaceHolder = OpaqueType::get();
|
||||||
TypeMap.insert(make_pair(Ty, PlaceHolder.get()));
|
TypeMap.insert(std::make_pair(Ty, PlaceHolder.get()));
|
||||||
|
|
||||||
switch (Ty->getPrimitiveID()) {
|
switch (Ty->getPrimitiveID()) {
|
||||||
case Type::MethodTyID: {
|
case Type::MethodTyID: {
|
||||||
|
@ -100,7 +100,7 @@ const Type *MutateStructTypes::ConvertType(const Type *Ty) {
|
||||||
|
|
||||||
// Refine our little placeholder value into a real type...
|
// Refine our little placeholder value into a real type...
|
||||||
cast<DerivedType>(PlaceHolder.get())->refineAbstractTypeTo(DestTy);
|
cast<DerivedType>(PlaceHolder.get())->refineAbstractTypeTo(DestTy);
|
||||||
TypeMap.insert(make_pair(Ty, PlaceHolder.get()));
|
TypeMap.insert(std::make_pair(Ty, PlaceHolder.get()));
|
||||||
|
|
||||||
return PlaceHolder.get();
|
return PlaceHolder.get();
|
||||||
}
|
}
|
||||||
|
@ -179,21 +179,20 @@ Value *MutateStructTypes::ConvertValue(const Value *V) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Ctor - Take a map that specifies what transformation to do for each field
|
// setTransforms - Take a map that specifies what transformation to do for each
|
||||||
// of the specified structure types. There is one element of the vector for
|
// field of the specified structure types. There is one element of the vector
|
||||||
// each field of the structure. The value specified indicates which slot of
|
// for each field of the structure. The value specified indicates which slot of
|
||||||
// the destination structure the field should end up in. A negative value
|
// the destination structure the field should end up in. A negative value
|
||||||
// indicates that the field should be deleted entirely.
|
// indicates that the field should be deleted entirely.
|
||||||
//
|
//
|
||||||
MutateStructTypes::MutateStructTypes(const map<const StructType*,
|
void MutateStructTypes::setTransforms(const TransformsType &XForm) {
|
||||||
vector<int> > &XForm) {
|
|
||||||
|
|
||||||
// Loop over the types and insert dummy entries into the type map so that
|
// Loop over the types and insert dummy entries into the type map so that
|
||||||
// recursive types are resolved properly...
|
// recursive types are resolved properly...
|
||||||
for (map<const StructType*, vector<int> >::const_iterator I = XForm.begin(),
|
for (map<const StructType*, vector<int> >::const_iterator I = XForm.begin(),
|
||||||
E = XForm.end(); I != E; ++I) {
|
E = XForm.end(); I != E; ++I) {
|
||||||
const StructType *OldTy = I->first;
|
const StructType *OldTy = I->first;
|
||||||
TypeMap.insert(make_pair(OldTy, OpaqueType::get()));
|
TypeMap.insert(std::make_pair(OldTy, OpaqueType::get()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Loop over the type specified and figure out what types they should become
|
// Loop over the type specified and figure out what types they should become
|
||||||
|
@ -229,17 +228,24 @@ MutateStructTypes::MutateStructTypes(const map<const StructType*,
|
||||||
cast<DerivedType>(OldTypeStub)->refineAbstractTypeTo(NSTy);
|
cast<DerivedType>(OldTypeStub)->refineAbstractTypeTo(NSTy);
|
||||||
|
|
||||||
// Add the transformation to the Transforms map.
|
// Add the transformation to the Transforms map.
|
||||||
Transforms.insert(make_pair(OldTy, make_pair(NSTy, InVec)));
|
Transforms.insert(std::make_pair(OldTy, std::make_pair(NSTy, InVec)));
|
||||||
|
|
||||||
DEBUG_MST(cerr << "Mutate " << OldTy << "\nTo " << NSTy << endl);
|
DEBUG_MST(cerr << "Mutate " << OldTy << "\nTo " << NSTy << endl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MutateStructTypes::clearTransforms() {
|
||||||
|
Transforms.clear();
|
||||||
|
TypeMap.clear();
|
||||||
|
GlobalMap.clear();
|
||||||
|
assert(LocalValueMap.empty() &&
|
||||||
|
"Local Value Map should always be empty between transformations!");
|
||||||
|
}
|
||||||
|
|
||||||
// doPassInitialization - This loops over global constants defined in the
|
// doInitialization - This loops over global constants defined in the
|
||||||
// module, converting them to their new type.
|
// module, converting them to their new type.
|
||||||
//
|
//
|
||||||
bool MutateStructTypes::doPassInitialization(Module *M) {
|
void MutateStructTypes::processGlobals(Module *M) {
|
||||||
// Loop through the methods in the module and create a new version of the
|
// Loop through the methods in the module and create a new version of the
|
||||||
// method to contained the transformed code. Don't use an iterator, because
|
// method to contained the transformed code. Don't use an iterator, because
|
||||||
// we will be adding values to the end of the vector, and it could be
|
// we will be adding values to the end of the vector, and it could be
|
||||||
|
@ -285,14 +291,12 @@ bool MutateStructTypes::doPassInitialization(Module *M) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// doPassFinalization - For this pass, all this does is remove the old versions
|
// removeDeadGlobals - For this pass, all this does is remove the old versions
|
||||||
// of the methods and global variables that we no longer need.
|
// of the methods and global variables that we no longer need.
|
||||||
bool MutateStructTypes::doPassFinalization(Module *M) {
|
void MutateStructTypes::removeDeadGlobals(Module *M) {
|
||||||
// The first half of the methods in the module have to go.
|
// The first half of the methods in the module have to go.
|
||||||
//unsigned NumMethods = M->size();
|
//unsigned NumMethods = M->size();
|
||||||
//unsigned NumGVars = M->gsize();
|
//unsigned NumGVars = M->gsize();
|
||||||
|
@ -313,20 +317,18 @@ bool MutateStructTypes::doPassFinalization(Module *M) {
|
||||||
else
|
else
|
||||||
++I;
|
++I;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// doPerMethodWork - This transforms the instructions of the method to use the
|
// transformMethod - This transforms the instructions of the method to use the
|
||||||
// new types.
|
// new types.
|
||||||
//
|
//
|
||||||
bool MutateStructTypes::doPerMethodWork(Method *m) {
|
void MutateStructTypes::transformMethod(Method *m) {
|
||||||
const Method *M = m;
|
const Method *M = m;
|
||||||
map<const GlobalValue*, GlobalValue*>::iterator GMI = GlobalMap.find(M);
|
map<const GlobalValue*, GlobalValue*>::iterator GMI = GlobalMap.find(M);
|
||||||
if (GMI == GlobalMap.end())
|
if (GMI == GlobalMap.end())
|
||||||
return false; // Do not affect one of our new methods that we are creating
|
return; // Do not affect one of our new methods that we are creating
|
||||||
|
|
||||||
Method *NewMeth = cast<Method>(GMI->second);
|
Method *NewMeth = cast<Method>(GMI->second);
|
||||||
|
|
||||||
|
@ -501,5 +503,14 @@ bool MutateStructTypes::doPerMethodWork(Method *m) {
|
||||||
}
|
}
|
||||||
|
|
||||||
LocalValueMap.clear();
|
LocalValueMap.clear();
|
||||||
return true;
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool MutateStructTypes::run(Module *M) {
|
||||||
|
processGlobals(M);
|
||||||
|
|
||||||
|
for_each(M->begin(), M->end(),
|
||||||
|
bind_obj(this, &MutateStructTypes::transformMethod));
|
||||||
|
|
||||||
|
removeDeadGlobals(M);
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,18 +58,18 @@ static unsigned getIndex(const vector<pair<unsigned, unsigned> > &Vec,
|
||||||
|
|
||||||
static inline void GetTransformation(const StructType *ST,
|
static inline void GetTransformation(const StructType *ST,
|
||||||
vector<int> &Transform,
|
vector<int> &Transform,
|
||||||
enum PrebuiltStructMutation::Transform XForm) {
|
enum SimpleStructMutation::Transform XForm) {
|
||||||
unsigned NumElements = ST->getElementTypes().size();
|
unsigned NumElements = ST->getElementTypes().size();
|
||||||
Transform.reserve(NumElements);
|
Transform.reserve(NumElements);
|
||||||
|
|
||||||
switch (XForm) {
|
switch (XForm) {
|
||||||
case PrebuiltStructMutation::SwapElements:
|
case SimpleStructMutation::SwapElements:
|
||||||
// The transformation to do is: just simply swap the elements
|
// The transformation to do is: just simply swap the elements
|
||||||
for (unsigned i = 0; i < NumElements; ++i)
|
for (unsigned i = 0; i < NumElements; ++i)
|
||||||
Transform.push_back(NumElements-i-1);
|
Transform.push_back(NumElements-i-1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PrebuiltStructMutation::SortElements: {
|
case SimpleStructMutation::SortElements: {
|
||||||
vector<pair<unsigned, unsigned> > ElList;
|
vector<pair<unsigned, unsigned> > ElList;
|
||||||
|
|
||||||
// Build mapping from index to size
|
// Build mapping from index to size
|
||||||
|
@ -87,26 +87,26 @@ static inline void GetTransformation(const StructType *ST,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// doPassInitialization - This does all of the work of the pass
|
SimpleStructMutation::TransformsType
|
||||||
//
|
SimpleStructMutation::getTransforms(Module *M, enum Transform XForm) {
|
||||||
PrebuiltStructMutation::TransformsType
|
|
||||||
PrebuiltStructMutation::getTransforms(Module *M, enum Transform XForm) {
|
// FIXME: These should be calculated by the Pass framework!
|
||||||
|
|
||||||
// We need to know which types to modify, and which types we CAN'T modify
|
// We need to know which types to modify, and which types we CAN'T modify
|
||||||
FindUsedTypes FUT/*(true)*/; // TODO: Do symbol tables as well
|
FindUsedTypes *FUT = new FindUsedTypes(/*true*/); // TODO: Do symbol tables as well
|
||||||
FindUnsafePointerTypes FUPT;
|
FindUnsafePointerTypes *FUPT = new FindUnsafePointerTypes();
|
||||||
|
|
||||||
// Simutaneously find all of the types used, and all of the types that aren't
|
// Simutaneously find all of the types used, and all of the types that aren't
|
||||||
// safe.
|
// safe.
|
||||||
//
|
//
|
||||||
vector<Pass*> Analyses;
|
PassManager Analyses;
|
||||||
Analyses.push_back(&FUT);
|
Analyses.add(FUT);
|
||||||
Analyses.push_back(&FUPT);
|
Analyses.add(FUPT);
|
||||||
Pass::runAllPasses(M, Analyses); // Do analyses
|
Analyses.run(M); // Do analyses
|
||||||
|
|
||||||
|
|
||||||
// Get the results out of the analyzers...
|
// Get the results out of the analyzers...
|
||||||
const set<PointerType*> &UnsafePTys = FUPT.getUnsafeTypes();
|
const set<PointerType*> &UnsafePTys = FUPT->getUnsafeTypes();
|
||||||
const set<const Type *> &UsedTypes = FUT.getTypes();
|
const set<const Type *> &UsedTypes = FUT->getTypes();
|
||||||
|
|
||||||
|
|
||||||
// Combine the two sets, weeding out non structure types. Closures in C++
|
// Combine the two sets, weeding out non structure types. Closures in C++
|
||||||
|
|
|
@ -23,7 +23,7 @@ using std::string;
|
||||||
|
|
||||||
// Add a prototype for printf if it is not already in the program.
|
// Add a prototype for printf if it is not already in the program.
|
||||||
//
|
//
|
||||||
bool InsertTraceCode::doPassInitialization(Module *M) {
|
bool InsertTraceCode::doInitialization(Module *M) {
|
||||||
SymbolTable *ST = M->getSymbolTable();
|
SymbolTable *ST = M->getSymbolTable();
|
||||||
const Type *SBP = PointerType::get(Type::SByteTy);
|
const Type *SBP = PointerType::get(Type::SByteTy);
|
||||||
const MethodType *MTy =
|
const MethodType *MTy =
|
||||||
|
|
|
@ -17,12 +17,12 @@
|
||||||
using std::vector;
|
using std::vector;
|
||||||
|
|
||||||
|
|
||||||
// doPassInitialization - For the lower allocations pass, this ensures that a
|
// doInitialization - For the lower allocations pass, this ensures that a
|
||||||
// module contains a declaration for a malloc and a free function.
|
// module contains a declaration for a malloc and a free function.
|
||||||
//
|
//
|
||||||
// This function is always successful.
|
// This function is always successful.
|
||||||
//
|
//
|
||||||
bool LowerAllocations::doPassInitialization(Module *M) {
|
bool LowerAllocations::doInitialization(Module *M) {
|
||||||
bool Changed = false;
|
bool Changed = false;
|
||||||
const MethodType *MallocType =
|
const MethodType *MallocType =
|
||||||
MethodType::get(PointerType::get(Type::SByteTy),
|
MethodType::get(PointerType::get(Type::SByteTy),
|
||||||
|
@ -55,10 +55,10 @@ bool LowerAllocations::doPassInitialization(Module *M) {
|
||||||
return Changed; // Always successful
|
return Changed; // Always successful
|
||||||
}
|
}
|
||||||
|
|
||||||
// doPerMethodWork - This method does the actual work of converting
|
// runOnMethod - This method does the actual work of converting
|
||||||
// instructions over, assuming that the pass has already been initialized.
|
// instructions over, assuming that the pass has already been initialized.
|
||||||
//
|
//
|
||||||
bool LowerAllocations::doPerMethodWork(Method *M) {
|
bool LowerAllocations::runOnMethod(Method *M) {
|
||||||
bool Changed = false;
|
bool Changed = false;
|
||||||
assert(MallocMeth && FreeMeth && M && "Pass not initialized!");
|
assert(MallocMeth && FreeMeth && M && "Pass not initialized!");
|
||||||
|
|
||||||
|
|
|
@ -63,19 +63,19 @@ int main(int argc, char **argv) {
|
||||||
// In addition to just parsing the input from GCC, we also want to spiff it up
|
// In addition to just parsing the input from GCC, we also want to spiff it up
|
||||||
// a little bit. Do this now.
|
// a little bit. Do this now.
|
||||||
//
|
//
|
||||||
std::vector<Pass*> Passes;
|
PassManager Passes;
|
||||||
Passes.push_back(new opt::DeadCodeElimination()); // Remove Dead code/vars
|
Passes.add(new opt::DeadCodeElimination()); // Remove Dead code/vars
|
||||||
Passes.push_back(new CleanupGCCOutput()); // Fix gccisms
|
Passes.add(new CleanupGCCOutput()); // Fix gccisms
|
||||||
Passes.push_back(new InductionVariableSimplify()); // Simplify indvars
|
Passes.add(new InductionVariableSimplify()); // Simplify indvars
|
||||||
Passes.push_back(new RaisePointerReferences()); // Eliminate casts
|
Passes.add(new RaisePointerReferences()); // Eliminate casts
|
||||||
Passes.push_back(new ConstantMerge()); // Merge dup global consts
|
Passes.add(new ConstantMerge()); // Merge dup global consts
|
||||||
Passes.push_back(new InstructionCombining()); // Combine silly seq's
|
Passes.add(new InstructionCombining()); // Combine silly seq's
|
||||||
Passes.push_back(new opt::DeadCodeElimination()); // Remove Dead code/vars
|
Passes.add(new opt::DeadCodeElimination()); // Remove Dead code/vars
|
||||||
|
|
||||||
// Run our queue of passes all at once now, efficiently. This form of
|
// Run our queue of passes all at once now, efficiently. This form of
|
||||||
// runAllPasses frees the Pass objects after runAllPasses completes.
|
// runAllPasses frees the Pass objects after runAllPasses completes.
|
||||||
//
|
//
|
||||||
Pass::runAllPassesAndFree(M.get(), Passes);
|
Passes.run(M.get());
|
||||||
|
|
||||||
WriteBytecodeToFile(M.get(), *Out);
|
WriteBytecodeToFile(M.get(), *Out);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -52,21 +52,20 @@ static inline string GetFileNameRoot(const string &InputFilename) {
|
||||||
// Native code generation for a specified target.
|
// Native code generation for a specified target.
|
||||||
//===---------------------------------------------------------------------===//
|
//===---------------------------------------------------------------------===//
|
||||||
|
|
||||||
class GenerateCodeForTarget : public Pass {
|
class GenerateCodeForTarget : public MethodPass {
|
||||||
TargetMachine &Target;
|
TargetMachine &Target;
|
||||||
public:
|
public:
|
||||||
inline GenerateCodeForTarget(TargetMachine &T) : Target(T) {}
|
inline GenerateCodeForTarget(TargetMachine &T) : Target(T) {}
|
||||||
|
|
||||||
// doPerMethodWork - This method does the actual work of generating code for
|
// runOnMethod - This method does the actual work of generating code for
|
||||||
// the specified method.
|
// the specified method.
|
||||||
//
|
//
|
||||||
bool doPerMethodWork(Method *M) {
|
bool runOnMethod(Method *M) {
|
||||||
if (!M->isExternal() && Target.compileMethod(M)) {
|
if (!M->isExternal() && Target.compileMethod(M)) {
|
||||||
cerr << "Error compiling " << InputFilename << "!\n";
|
cerr << "Error compiling " << InputFilename << "!\n";
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -85,8 +84,7 @@ public:
|
||||||
inline EmitAssembly(const TargetMachine &T, std::ostream *O, bool D)
|
inline EmitAssembly(const TargetMachine &T, std::ostream *O, bool D)
|
||||||
: Target(T), Out(O), DeleteStream(D) {}
|
: Target(T), Out(O), DeleteStream(D) {}
|
||||||
|
|
||||||
|
virtual bool run(Module *M) {
|
||||||
virtual bool doPassFinalization(Module *M) {
|
|
||||||
Target.emitAssembly(M, *Out);
|
Target.emitAssembly(M, *Out);
|
||||||
|
|
||||||
if (DeleteStream) delete Out;
|
if (DeleteStream) delete Out;
|
||||||
|
@ -95,6 +93,7 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//===---------------------------------------------------------------------===//
|
//===---------------------------------------------------------------------===//
|
||||||
// Function main()
|
// Function main()
|
||||||
//
|
//
|
||||||
|
@ -119,18 +118,18 @@ int main(int argc, char **argv) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build up all of the passes that we want to do to the module...
|
// Build up all of the passes that we want to do to the module...
|
||||||
std::vector<Pass*> Passes;
|
PassManager Passes;
|
||||||
|
|
||||||
// Hoist constants out of PHI nodes into predecessor BB's
|
// Hoist constants out of PHI nodes into predecessor BB's
|
||||||
Passes.push_back(new HoistPHIConstants());
|
Passes.add(new HoistPHIConstants());
|
||||||
|
|
||||||
if (TraceBBValues || TraceMethodValues) { // If tracing enabled...
|
if (TraceBBValues || TraceMethodValues) { // If tracing enabled...
|
||||||
// Insert trace code in all methods in the module
|
// Insert trace code in all methods in the module
|
||||||
Passes.push_back(new InsertTraceCode(TraceBBValues,
|
Passes.add(new InsertTraceCode(TraceBBValues,
|
||||||
TraceBBValues ||TraceMethodValues));
|
TraceBBValues ||TraceMethodValues));
|
||||||
|
|
||||||
// Eliminate duplication in constant pool
|
// Eliminate duplication in constant pool
|
||||||
Passes.push_back(new DynamicConstantMerge());
|
Passes.add(new DynamicConstantMerge());
|
||||||
|
|
||||||
// Then write out the module with tracing code before code generation
|
// Then write out the module with tracing code before code generation
|
||||||
assert(InputFilename != "-" &&
|
assert(InputFilename != "-" &&
|
||||||
|
@ -152,20 +151,20 @@ int main(int argc, char **argv) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Passes.push_back(new WriteBytecodePass(os, true));
|
Passes.add(new WriteBytecodePass(os, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Replace malloc and free instructions with library calls.
|
// Replace malloc and free instructions with library calls.
|
||||||
// Do this after tracing until lli implements these lib calls.
|
// Do this after tracing until lli implements these lib calls.
|
||||||
// For now, it will emulate malloc and free internally.
|
// For now, it will emulate malloc and free internally.
|
||||||
Passes.push_back(new LowerAllocations(Target.DataLayout));
|
Passes.add(new LowerAllocations(Target.DataLayout));
|
||||||
|
|
||||||
// If LLVM dumping after transformations is requested, add it to the pipeline
|
// If LLVM dumping after transformations is requested, add it to the pipeline
|
||||||
if (DumpAsm)
|
if (DumpAsm)
|
||||||
Passes.push_back(new PrintModulePass("Code after xformations: \n",&cerr));
|
Passes.add(new PrintMethodPass("Code after xformations: \n",&cerr));
|
||||||
|
|
||||||
// Generate Target code...
|
// Generate Target code...
|
||||||
Passes.push_back(new GenerateCodeForTarget(Target));
|
Passes.add(new GenerateCodeForTarget(Target));
|
||||||
|
|
||||||
if (!DoNotEmitAssembly) { // If asm output is enabled...
|
if (!DoNotEmitAssembly) { // If asm output is enabled...
|
||||||
// Figure out where we are going to send the output...
|
// Figure out where we are going to send the output...
|
||||||
|
@ -203,12 +202,11 @@ int main(int argc, char **argv) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Output assembly language to the .s file
|
// Output assembly language to the .s file
|
||||||
Passes.push_back(new EmitAssembly(Target, Out, Out != &std::cout));
|
Passes.add(new EmitAssembly(Target, Out, Out != &std::cout));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run our queue of passes all at once now, efficiently. This form of
|
// Run our queue of passes all at once now, efficiently.
|
||||||
// runAllPasses frees the Pass objects after runAllPasses completes.
|
Passes.run(M.get());
|
||||||
Pass::runAllPassesAndFree(M.get(), Passes);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,14 +34,13 @@ enum Opts {
|
||||||
indvars, instcombine, sccp, adce, raise,
|
indvars, instcombine, sccp, adce, raise,
|
||||||
|
|
||||||
// Interprocedural optimizations...
|
// Interprocedural optimizations...
|
||||||
globaldce, swapstructs,
|
globaldce, swapstructs, sortstructs,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
enum Opts OptID;
|
enum Opts OptID;
|
||||||
Pass *ThePass;
|
Pass *ThePass;
|
||||||
} OptTable[] = {
|
} OptTable[] = {
|
||||||
{ swapstructs, 0 },
|
|
||||||
{ dce , new opt::DeadCodeElimination() },
|
{ dce , new opt::DeadCodeElimination() },
|
||||||
{ constprop , new opt::ConstantPropogation() },
|
{ constprop , new opt::ConstantPropogation() },
|
||||||
{ inlining , new opt::MethodInlining() },
|
{ inlining , new opt::MethodInlining() },
|
||||||
|
@ -55,8 +54,11 @@ struct {
|
||||||
{ raise , new RaisePointerReferences() },
|
{ raise , new RaisePointerReferences() },
|
||||||
{ trace , new InsertTraceCode(true, true) },
|
{ trace , new InsertTraceCode(true, true) },
|
||||||
{ tracem , new InsertTraceCode(false, true) },
|
{ tracem , new InsertTraceCode(false, true) },
|
||||||
{ print , new PrintModulePass("Current Method: \n",&cerr) },
|
{ print , new PrintMethodPass("Current Method: \n",&cerr) },
|
||||||
{ cleangcc , new CleanupGCCOutput() },
|
{ cleangcc , new CleanupGCCOutput() },
|
||||||
|
{ globaldce , new GlobalDCE() },
|
||||||
|
{ swapstructs, new SimpleStructMutation(SimpleStructMutation::SwapElements) },
|
||||||
|
{ sortstructs, new SimpleStructMutation(SimpleStructMutation::SortElements) },
|
||||||
};
|
};
|
||||||
|
|
||||||
cl::String InputFilename ("", "Load <arg> file to optimize", cl::NoFlags, "-");
|
cl::String InputFilename ("", "Load <arg> file to optimize", cl::NoFlags, "-");
|
||||||
|
@ -78,6 +80,7 @@ cl::EnumList<enum Opts> OptimizationList(cl::NoFlags,
|
||||||
|
|
||||||
clEnumVal(globaldce , "Remove unreachable globals"),
|
clEnumVal(globaldce , "Remove unreachable globals"),
|
||||||
clEnumVal(swapstructs, "Swap structure types around"),
|
clEnumVal(swapstructs, "Swap structure types around"),
|
||||||
|
clEnumVal(sortstructs, "Sort structure elements"),
|
||||||
|
|
||||||
clEnumVal(cleangcc , "Cleanup GCC Output"),
|
clEnumVal(cleangcc , "Cleanup GCC Output"),
|
||||||
clEnumVal(raise , "Raise to Higher Level"),
|
clEnumVal(raise , "Raise to Higher Level"),
|
||||||
|
@ -95,18 +98,7 @@ static void RunOptimization(Module *M, enum Opts Opt) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Special cases that haven't been fit into a consistent framework yet...
|
cerr << "Optimization tables inconsistent!!\n";
|
||||||
switch (Opt) {
|
|
||||||
case globaldce: {
|
|
||||||
GlobalDCE GDCE; GDCE.run(M); return;
|
|
||||||
}
|
|
||||||
case swapstructs: {
|
|
||||||
PrebuiltStructMutation SM(M, PrebuiltStructMutation::SortElements);
|
|
||||||
SM.run(M); return;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
cerr << "Optimization tables inconsistent!!\n";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
|
@ -118,6 +110,8 @@ int main(int argc, char **argv) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PassManager Passes;
|
||||||
|
|
||||||
// Run all of the optimizations specified on the command line
|
// Run all of the optimizations specified on the command line
|
||||||
for (unsigned i = 0; i < OptimizationList.size(); ++i)
|
for (unsigned i = 0; i < OptimizationList.size(); ++i)
|
||||||
RunOptimization(M.get(), OptimizationList[i]);
|
RunOptimization(M.get(), OptimizationList[i]);
|
||||||
|
|
Loading…
Reference in New Issue