opt.cpp revision 22d26d7c7d7c9666d0da0e51250586da5a0744da
1//===----------------------------------------------------------------------===// 2// LLVM 'OPT' UTILITY 3// 4// Optimizations may be specified an arbitrary number of times on the command 5// line, they are run in the order specified. 6// 7//===----------------------------------------------------------------------===// 8 9#include "llvm/Module.h" 10#include "llvm/PassManager.h" 11#include "llvm/Bytecode/Reader.h" 12#include "llvm/Bytecode/WriteBytecodePass.h" 13#include "llvm/Assembly/PrintModulePass.h" 14#include "llvm/Analysis/Verifier.h" 15#include "llvm/Transforms/UnifyMethodExitNodes.h" 16#include "llvm/Transforms/ConstantMerge.h" 17#include "llvm/Transforms/CleanupGCCOutput.h" 18#include "llvm/Transforms/LevelChange.h" 19#include "llvm/Transforms/MethodInlining.h" 20#include "llvm/Transforms/SymbolStripping.h" 21#include "llvm/Transforms/ChangeAllocations.h" 22#include "llvm/Transforms/IPO/SimpleStructMutation.h" 23#include "llvm/Transforms/IPO/GlobalDCE.h" 24#include "llvm/Transforms/Scalar/DCE.h" 25#include "llvm/Transforms/Scalar/ConstantProp.h" 26#include "llvm/Transforms/Scalar/IndVarSimplify.h" 27#include "llvm/Transforms/Scalar/InstructionCombining.h" 28#include "llvm/Transforms/Scalar/PromoteMemoryToRegister.h" 29#include "llvm/Transforms/Instrumentation/TraceValues.h" 30#include "Support/CommandLine.h" 31#include <fstream> 32#include <memory> 33 34// Opts enum - All of the transformations we can do... 35enum Opts { 36 // Basic optimizations 37 dce, constprop, inlining, constmerge, strip, mstrip, mergereturn, 38 39 // Miscellaneous Transformations 40 trace, tracem, raiseallocs, cleangcc, 41 42 // Printing and verifying... 43 print, verify, 44 45 // More powerful optimizations 46 indvars, instcombine, sccp, adce, raise, mem2reg, 47 48 // Interprocedural optimizations... 49 globaldce, swapstructs, sortstructs, 50}; 51 52 53// New template functions - Provide functions that return passes of specified 54// types, with specified arguments... 55// 56template<class PassClass> 57Pass *New() { 58 return new PassClass(); 59} 60 61template<class PassClass, typename ArgTy1, ArgTy1 Arg1> 62Pass *New() { 63 return new PassClass(Arg1); 64} 65 66template<class PassClass, typename ArgTy1, ArgTy1 Arg1, 67 typename ArgTy2, ArgTy1 Arg2> 68Pass *New() { 69 return new PassClass(Arg1, Arg2); 70} 71 72static Pass *NewPrintMethodPass() { 73 return new PrintMethodPass("Current Method: \n", &cerr); 74} 75 76// OptTable - Correlate enum Opts to Pass constructors... 77// 78struct { 79 enum Opts OptID; 80 Pass * (*PassCtor)(); 81} OptTable[] = { 82 { dce , New<DeadCodeElimination> }, 83 { constprop , New<ConstantPropogation> }, 84 { inlining , New<MethodInlining> }, 85 { constmerge , New<ConstantMerge> }, 86 { strip , New<SymbolStripping> }, 87 { mstrip , New<FullSymbolStripping> }, 88 { mergereturn, New<UnifyMethodExitNodes> }, 89 90 { indvars , New<InductionVariableSimplify> }, 91 { instcombine, New<InstructionCombining> }, 92 { sccp , New<SCCPPass> }, 93 { adce , New<AgressiveDCE> }, 94 { raise , New<RaisePointerReferences> }, 95 { mem2reg , newPromoteMemoryToRegister }, 96 97 { trace , New<InsertTraceCode, bool, true, bool, true> }, 98 { tracem , New<InsertTraceCode, bool, false, bool, true> }, 99 { print , NewPrintMethodPass }, 100 { verify , createVerifierPass }, 101 { raiseallocs, New<RaiseAllocations> }, 102 { cleangcc , New<CleanupGCCOutput> }, 103 { globaldce , New<GlobalDCE> }, 104 { swapstructs, New<SimpleStructMutation, SimpleStructMutation::Transform, 105 SimpleStructMutation::SwapElements>}, 106 { sortstructs, New<SimpleStructMutation, SimpleStructMutation::Transform, 107 SimpleStructMutation::SortElements>}, 108}; 109 110// Command line option handling code... 111// 112cl::String InputFilename ("", "Load <arg> file to optimize", cl::NoFlags, "-"); 113cl::String OutputFilename("o", "Override output filename", cl::NoFlags, ""); 114cl::Flag Force ("f", "Overwrite output files", cl::NoFlags, false); 115cl::Flag PrintEachXForm("p", "Print module after each transformation"); 116cl::Flag Quiet ("q", "Don't print modifying pass names", 0, false); 117cl::Alias QuietA ("quiet", "Alias for -q", cl::NoFlags, Quiet); 118cl::EnumList<enum Opts> OptimizationList(cl::NoFlags, 119 clEnumVal(dce , "Dead Code Elimination"), 120 clEnumVal(constprop , "Simple constant propogation"), 121 clEnumValN(inlining , "inline", "Method integration"), 122 clEnumVal(constmerge , "Merge identical global constants"), 123 clEnumVal(strip , "Strip symbols"), 124 clEnumVal(mstrip , "Strip module symbols"), 125 clEnumVal(mergereturn, "Unify method exit nodes"), 126 127 clEnumVal(indvars , "Simplify Induction Variables"), 128 clEnumVal(instcombine, "Combine redundant instructions"), 129 clEnumVal(sccp , "Sparse Conditional Constant Propogation"), 130 clEnumVal(adce , "Agressive DCE"), 131 clEnumVal(mem2reg , "Promote alloca locations to registers"), 132 133 clEnumVal(globaldce , "Remove unreachable globals"), 134 clEnumVal(swapstructs, "Swap structure types around"), 135 clEnumVal(sortstructs, "Sort structure elements"), 136 137 clEnumVal(raiseallocs, "Raise allocations from calls to instructions"), 138 clEnumVal(cleangcc , "Cleanup GCC Output"), 139 clEnumVal(raise , "Raise to Higher Level"), 140 clEnumVal(trace , "Insert BB & Method trace code"), 141 clEnumVal(tracem , "Insert Method trace code only"), 142 143 clEnumVal(print , "Print working method to stderr"), 144 clEnumVal(verify , "Verify module is well formed"), 1450); 146 147 148 149int main(int argc, char **argv) { 150 cl::ParseCommandLineOptions(argc, argv, 151 " llvm .bc -> .bc modular optimizer\n"); 152 153 // Load the input module... 154 std::auto_ptr<Module> M(ParseBytecodeFile(InputFilename)); 155 if (M.get() == 0) { 156 cerr << "bytecode didn't read correctly.\n"; 157 return 1; 158 } 159 160 // Figure out what stream we are supposed to write to... 161 std::ostream *Out = &std::cout; // Default to printing to stdout... 162 if (OutputFilename != "") { 163 if (!Force && std::ifstream(OutputFilename.c_str())) { 164 // If force is not specified, make sure not to overwrite a file! 165 cerr << "Error opening '" << OutputFilename << "': File exists!\n" 166 << "Use -f command line argument to force output\n"; 167 return 1; 168 } 169 Out = new std::ofstream(OutputFilename.c_str()); 170 171 if (!Out->good()) { 172 cerr << "Error opening " << OutputFilename << "!\n"; 173 return 1; 174 } 175 } 176 177 // Create a PassManager to hold and optimize the collection of passes we are 178 // about to build... 179 // 180 PassManager Passes; 181 182 // Create a new optimization pass for each one specified on the command line 183 for (unsigned i = 0; i < OptimizationList.size(); ++i) { 184 enum Opts Opt = OptimizationList[i]; 185 for (unsigned j = 0; j < sizeof(OptTable)/sizeof(OptTable[0]); ++j) 186 if (Opt == OptTable[j].OptID) { 187 Passes.add(OptTable[j].PassCtor()); 188 break; 189 } 190 191 if (PrintEachXForm) 192 Passes.add(new PrintModulePass(&std::cerr)); 193 } 194 195 // Check that the module is well formed on completion of optimization 196 Passes.add(createVerifierPass()); 197 198 // Write bytecode out to disk or cout as the last step... 199 Passes.add(new WriteBytecodePass(Out, Out != &std::cout)); 200 201 // Now that we have all of the passes ready, run them. 202 if (Passes.run(M.get()) && !Quiet) 203 cerr << "Program modified.\n"; 204 205 return 0; 206} 207