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