bbf1489ca62e214ddf00c35bd95d010c4573cd34
[oota-llvm.git] / tools / opt / opt.cpp
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/Bytecode/Reader.h"
11 #include "llvm/Bytecode/Writer.h"
12 #include "llvm/Optimizations/AllOpts.h"
13 #include "llvm/Transforms/Instrumentation/TraceValues.h"
14 #include "llvm/Assembly/PrintModulePass.h"
15 #include "llvm/Transforms/ConstantMerge.h"
16 #include "llvm/Transforms/CleanupGCCOutput.h"
17 #include "llvm/Transforms/LevelChange.h"
18 #include "llvm/Transforms/IPO/SimpleStructMutation.h"
19 #include "llvm/Transforms/IPO/GlobalDCE.h"
20 #include "llvm/Transforms/Scalar/IndVarSimplify.h"
21 #include "llvm/Transforms/Scalar/InstructionCombining.h"
22 #include "Support/CommandLine.h"
23 #include <fstream>
24 #include <memory>
25
26 enum Opts {
27   // Basic optimizations
28   dce, constprop, inlining, constmerge, strip, mstrip,
29
30   // Miscellaneous Transformations
31   trace, tracem, print, cleangcc,
32
33   // More powerful optimizations
34   indvars, instcombine, sccp, adce, raise,
35
36   // Interprocedural optimizations...
37   globaldce, swapstructs, sortstructs,
38 };
39
40 struct {
41   enum Opts OptID;
42   Pass *ThePass;
43 } OptTable[] = {
44   { dce        , new opt::DeadCodeElimination() },
45   { constprop  , new opt::ConstantPropogation() }, 
46   { inlining   , new opt::MethodInlining() },
47   { constmerge , new ConstantMerge() },
48   { strip      , new opt::SymbolStripping() },
49   { mstrip     , new opt::FullSymbolStripping() },
50   { indvars    , new InductionVariableSimplify() },
51   { instcombine, new InstructionCombining() },
52   { sccp       , new opt::SCCPPass() },
53   { adce       , new opt::AgressiveDCE() },
54   { raise      , new RaisePointerReferences() },
55   { trace      , new InsertTraceCode(true, true) },
56   { tracem     , new InsertTraceCode(false, true) },
57   { print      , new PrintMethodPass("Current Method: \n",&cerr) },
58   { cleangcc   , new CleanupGCCOutput() },
59   { globaldce  , new GlobalDCE() },
60   { swapstructs, new SimpleStructMutation(SimpleStructMutation::SwapElements) },
61   { sortstructs, new SimpleStructMutation(SimpleStructMutation::SortElements) },
62 };
63
64 cl::String InputFilename ("", "Load <arg> file to optimize", cl::NoFlags, "-");
65 cl::String OutputFilename("o", "Override output filename", cl::NoFlags, "");
66 cl::Flag   Force         ("f", "Overwrite output files", cl::NoFlags, false);
67 cl::Flag   Quiet         ("q", "Don't print modifying pass names", 0, false);
68 cl::Alias  QuietA        ("quiet", "Alias for -q", cl::NoFlags, Quiet);
69 cl::EnumList<enum Opts> OptimizationList(cl::NoFlags,
70   clEnumVal(dce        , "Dead Code Elimination"),
71   clEnumVal(constprop  , "Simple Constant Propogation"),
72  clEnumValN(inlining   , "inline", "Method Integration"),
73   clEnumVal(constmerge , "Merge identical global constants"),
74   clEnumVal(strip      , "Strip Symbols"),
75   clEnumVal(mstrip     , "Strip Module Symbols"),
76   clEnumVal(indvars    , "Simplify Induction Variables"),
77   clEnumVal(instcombine, "Simplify Induction Variables"),
78   clEnumVal(sccp       , "Sparse Conditional Constant Propogation"),
79   clEnumVal(adce       , "Agressive DCE"),
80
81   clEnumVal(globaldce  , "Remove unreachable globals"),
82   clEnumVal(swapstructs, "Swap structure types around"),
83   clEnumVal(sortstructs, "Sort structure elements"),
84
85   clEnumVal(cleangcc   , "Cleanup GCC Output"),
86   clEnumVal(raise      , "Raise to Higher Level"),
87   clEnumVal(trace      , "Insert BB & Method trace code"),
88   clEnumVal(tracem     , "Insert Method trace code only"),
89   clEnumVal(print      , "Print working method to stderr"),
90 0);
91
92 static void RunOptimization(Module *M, enum Opts Opt) {
93   for (unsigned j = 0; j < sizeof(OptTable)/sizeof(OptTable[0]); ++j)
94     if (Opt == OptTable[j].OptID) {
95       if (OptTable[j].ThePass->run(M) && !Quiet)
96         cerr << OptimizationList.getArgName(Opt)
97              << " pass made modifications!\n";
98       return;
99     }
100   
101   cerr << "Optimization tables inconsistent!!\n";
102 }
103
104 int main(int argc, char **argv) {
105   cl::ParseCommandLineOptions(argc, argv,
106                               " llvm .bc -> .bc modular optimizer\n");
107   std::auto_ptr<Module> M(ParseBytecodeFile(InputFilename));
108   if (M.get() == 0) {
109     cerr << "bytecode didn't read correctly.\n";
110     return 1;
111   }
112
113   PassManager Passes;
114
115   // Run all of the optimizations specified on the command line
116   for (unsigned i = 0; i < OptimizationList.size(); ++i)
117     RunOptimization(M.get(), OptimizationList[i]);
118
119   std::ostream *Out = &std::cout;  // Default to printing to stdout...
120   if (OutputFilename != "") {
121     if (!Force && !std::ifstream(OutputFilename.c_str())) {
122       // If force is not specified, make sure not to overwrite a file!
123       cerr << "Error opening '" << OutputFilename << "': File exists!\n"
124            << "Use -f command line argument to force output\n";
125       return 1;
126     }
127     Out = new std::ofstream(OutputFilename.c_str());
128
129     if (!Out->good()) {
130       cerr << "Error opening " << OutputFilename << "!\n";
131       return 1;
132     }
133   }
134
135   // Okay, we're done now... write out result...
136   WriteBytecodeToFile(M.get(), *Out);
137
138   if (Out != &cout) delete Out;
139   return 0;
140 }