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