8eb15fd5d40e3d32538e0b03b0245270f56e187e
[oota-llvm.git] / tools / analyze / analyze.cpp
1 //===----------------------------------------------------------------------===//
2 // The LLVM analyze utility
3 //
4 // This utility is designed to print out the results of running various analysis
5 // passes on a program.  This is useful for understanding a program, or for 
6 // debugging an analysis pass.
7 //
8 //  analyze --help           - Output information about command line switches
9 //  analyze --quiet          - Do not print analysis name before output
10 //
11 //===----------------------------------------------------------------------===//
12
13 #include "llvm/Module.h"
14 #include "llvm/iPHINode.h"
15 #include "llvm/Type.h"
16 #include "llvm/PassManager.h"
17 #include "llvm/Bytecode/Reader.h"
18 #include "llvm/Assembly/Parser.h"
19 #include "llvm/Assembly/PrintModulePass.h"
20 #include "llvm/Assembly/Writer.h"
21 #include "llvm/Analysis/Writer.h"
22 #include "llvm/Analysis/InstForest.h"
23 #include "llvm/Analysis/Dominators.h"
24 #include "llvm/Analysis/IntervalPartition.h"
25 #include "llvm/Analysis/Expressions.h"
26 #include "llvm/Analysis/InductionVariable.h"
27 #include "llvm/Analysis/CallGraph.h"
28 #include "llvm/Analysis/LoopInfo.h"
29 #include "llvm/Analysis/DataStructure.h"
30 #include "llvm/Analysis/FindUnsafePointerTypes.h"
31 #include "llvm/Analysis/FindUsedTypes.h"
32 #include "llvm/Support/InstIterator.h"
33 #include "Support/CommandLine.h"
34 #include <algorithm>
35
36 using std::ostream;
37 using std::string;
38
39 //===----------------------------------------------------------------------===//
40 // printPass - Specify how to print out a pass.  For most passes, the standard
41 // way of using operator<< works great, so we use it directly...
42 //
43 template<class PassType>
44 static void printPass(PassType &P, ostream &O, Module &M) {
45   O << P;
46 }
47
48 template<class PassType>
49 static void printPass(PassType &P, ostream &O, Function &F) {
50   O << P;
51 }
52
53 // Other classes require more information to print out information, so we
54 // specialize the template here for them...
55 //
56 template<>
57 static void printPass(LocalDataStructures &P, ostream &O, Module &M) {
58   P.print(O, &M);
59 }
60 template<>
61 static void printPass(BUDataStructures &P, ostream &O, Module &M) {
62   P.print(O, &M);
63 }
64
65 template<>
66 static void printPass(FindUsedTypes &FUT, ostream &O, Module &M) {
67   FUT.printTypes(O, &M);
68 }
69
70 template<>
71 static void printPass(FindUnsafePointerTypes &FUPT, ostream &O, Module &M) {
72   FUPT.printResults(&M, O);
73 }
74
75
76
77 template <class PassType, class PassName>
78 class PassPrinter;  // Do not implement
79
80 template <class PassName>
81 class PassPrinter<Pass, PassName> : public Pass {
82   const AnalysisID ID;
83 public:
84   PassPrinter(AnalysisID id) : ID(id) {}
85
86   const char *getPassName() const { return "IP Pass Printer"; }
87   
88   virtual bool run(Module &M) {
89     printPass(getAnalysis<PassName>(ID), std::cout, M);
90     return false;
91   }
92
93   virtual void getAnalysisUsage(AnalysisUsage &AU) const {
94     AU.addRequired(ID);
95   }
96 };
97
98 template <class PassName>
99 class PassPrinter<FunctionPass, PassName> : public FunctionPass {
100   const AnalysisID ID;
101 public:
102   PassPrinter(AnalysisID id) : ID(id) {}
103
104     const char *getPassName() const { return "Function Pass Printer"; }
105   
106   virtual bool runOnFunction(Function &F) {
107     std::cout << "Running on function '" << F.getName() << "'\n";
108     printPass(getAnalysis<PassName>(ID), std::cout, F);
109     return false;
110   }
111
112   virtual void getAnalysisUsage(AnalysisUsage &AU) const {
113     AU.addRequired(ID);
114     AU.setPreservesAll();
115   }
116 };
117
118
119
120 template <class PassType, class PassName, AnalysisID &ID>
121 Pass *New() {
122   return new PassPrinter<PassType, PassName>(ID);
123 }
124 template <class PassType, class PassName>
125 Pass *New() {
126   return new PassPrinter<PassType, PassName>(PassName::ID);
127 }
128
129
130 Pass *createPrintFunctionPass() {
131   return new PrintFunctionPass("", &std::cout);
132 }
133 Pass *createPrintModulePass() {
134   return new PrintModulePass(&std::cout);
135 }
136
137 struct InstForestHelper : public FunctionPass {
138   const char *getPassName() const { return "InstForest Printer"; }
139
140   void doit(Function &F) {
141     std::cout << InstForest<char>(&F);
142   }
143
144   virtual void getAnalysisUsage(AnalysisUsage &AU) const {
145     AU.setPreservesAll();
146   }
147 };
148
149 struct IndVars : public FunctionPass {
150   const char *getPassName() const { return "IndVars Printer"; }
151
152   void doit(Function &F) {
153     LoopInfo &LI = getAnalysis<LoopInfo>();
154     for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I)
155       if (PHINode *PN = dyn_cast<PHINode>(*I)) {
156         InductionVariable IV(PN, &LI);
157         if (IV.InductionType != InductionVariable::Unknown)
158           std::cout << IV;
159       }
160   }
161
162   void getAnalysisUsage(AnalysisUsage &AU) const {
163     AU.addRequired(LoopInfo::ID);
164     AU.setPreservesAll();
165   }
166 };
167
168 struct Exprs : public FunctionPass {
169   const char *getPassName() const { return "Expression Printer"; }
170
171   static void doit(Function &F) {
172     std::cout << "Classified expressions for: " << F.getName() << "\n";
173     for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) {
174       std::cout << *I;
175       
176       if ((*I)->getType() == Type::VoidTy) continue;
177       analysis::ExprType R = analysis::ClassifyExpression(*I);
178       if (R.Var == *I) continue;  // Doesn't tell us anything
179       
180       std::cout << "\t\tExpr =";
181       switch (R.ExprTy) {
182       case analysis::ExprType::ScaledLinear:
183         WriteAsOperand(std::cout << "(", (Value*)R.Scale) << " ) *";
184         // fall through
185       case analysis::ExprType::Linear:
186         WriteAsOperand(std::cout << "(", R.Var) << " )";
187         if (R.Offset == 0) break;
188         else std::cout << " +";
189         // fall through
190       case analysis::ExprType::Constant:
191         if (R.Offset) WriteAsOperand(std::cout, (Value*)R.Offset);
192         else std::cout << " 0";
193         break;
194       }
195       std::cout << "\n\n";
196     }
197   }
198   virtual void getAnalysisUsage(AnalysisUsage &AU) const {
199     AU.setPreservesAll();
200   }
201 };
202
203
204 template<class TraitClass>
205 struct PrinterPass : public TraitClass {
206   PrinterPass() {}
207
208   virtual bool runOnFunction(Function &F) {
209     std::cout << "Running on function '" << F.getName() << "'\n";
210
211     TraitClass::doit(F);
212     return false;
213   }
214 };
215
216
217 template<class PassClass>
218 Pass *Create() {
219   return new PassClass();
220 }
221
222
223
224 enum Ans {
225   // global analyses
226   print, intervals, exprs, instforest, loops, indvars,
227
228   // ip analyses
229   printmodule, callgraph, datastructure, budatastructure,
230   printusedtypes, unsafepointertypes,
231
232   domset, idom, domtree, domfrontier,
233   postdomset, postidom, postdomtree, postdomfrontier,
234 };
235
236 static cl::opt<string>
237 InputFilename(cl::Positional, cl::desc("<input file>"), cl::init("-"),
238               cl::value_desc("filename"));
239
240 static cl::opt<bool> Quiet("q", cl::desc("Don't print analysis pass names"));
241 static cl::alias    QuietA("quiet", cl::desc("Alias for -q"),
242                            cl::aliasopt(Quiet));
243
244 static cl::list<enum Ans>
245 AnalysesList(cl::desc("Analyses available:"),
246              cl::values(
247   clEnumVal(print          , "Print each function"),
248   clEnumVal(intervals      , "Print Interval Partitions"),
249   clEnumVal(exprs          , "Classify Expressions"),
250   clEnumVal(instforest     , "Print Instruction Forest"),
251   clEnumVal(loops          , "Print natural loops"),
252   clEnumVal(indvars        , "Print Induction Variables"),
253
254   clEnumVal(printmodule    , "Print entire module"),
255   clEnumVal(callgraph      , "Print Call Graph"),
256   clEnumVal(datastructure  , "Print data structure information"),
257   clEnumVal(budatastructure, "Print bottom-up data structure information"),
258   clEnumVal(printusedtypes , "Print types used by module"),
259   clEnumVal(unsafepointertypes, "Print unsafe pointer types"),
260
261   clEnumVal(domset         , "Print Dominator Sets"),
262   clEnumVal(idom           , "Print Immediate Dominators"),
263   clEnumVal(domtree        , "Print Dominator Tree"),
264   clEnumVal(domfrontier    , "Print Dominance Frontier"),
265
266   clEnumVal(postdomset     , "Print Postdominator Sets"),
267   clEnumVal(postidom       , "Print Immediate Postdominators"),
268   clEnumVal(postdomtree    , "Print Post Dominator Tree"),
269   clEnumVal(postdomfrontier, "Print Postdominance Frontier"),
270 0));
271
272
273 struct {
274   enum Ans AnID;
275   Pass *(*PassConstructor)();
276 } AnTable[] = {
277   // Global analyses
278   { print             , createPrintFunctionPass                 },
279   { intervals         , New<FunctionPass, IntervalPartition>    },
280   { loops             , New<FunctionPass, LoopInfo>             },
281   { instforest        , Create<PrinterPass<InstForestHelper> >  },
282   { indvars           , Create<PrinterPass<IndVars> >           },
283   { exprs             , Create<PrinterPass<Exprs> >             },
284
285   // IP Analyses...
286   { printmodule       , createPrintModulePass             },
287   { printusedtypes    , New<Pass, FindUsedTypes>          },
288   { callgraph         , New<Pass, CallGraph>              },
289   { datastructure     , New<Pass, LocalDataStructures>    },
290   { budatastructure   , New<Pass, BUDataStructures>       },
291   { unsafepointertypes, New<Pass, FindUnsafePointerTypes> },
292
293   // Dominator analyses
294   { domset            , New<FunctionPass, DominatorSet>        },
295   { idom              , New<FunctionPass, ImmediateDominators> },
296   { domtree           , New<FunctionPass, DominatorTree>       },
297   { domfrontier       , New<FunctionPass, DominanceFrontier>   },
298
299   { postdomset        , New<FunctionPass, DominatorSet, DominatorSet::PostDomID> },
300   { postidom          , New<FunctionPass, ImmediateDominators, ImmediateDominators::PostDomID> },
301   { postdomtree       , New<FunctionPass, DominatorTree, DominatorTree::PostDomID> },
302   { postdomfrontier   , New<FunctionPass, DominanceFrontier, DominanceFrontier::PostDomID> },
303 };
304
305 int main(int argc, char **argv) {
306   cl::ParseCommandLineOptions(argc, argv, " llvm analysis printer tool\n");
307
308   Module *CurMod = 0;
309   try {
310     CurMod = ParseBytecodeFile(InputFilename);
311     if (!CurMod && !(CurMod = ParseAssemblyFile(InputFilename))){
312       std::cerr << "Input file didn't read correctly.\n";
313       return 1;
314     }
315   } catch (const ParseException &E) {
316     std::cerr << E.getMessage() << "\n";
317     return 1;
318   }
319
320   // Create a PassManager to hold and optimize the collection of passes we are
321   // about to build...
322   //
323   PassManager Analyses;
324
325   // Loop over all of the analyses looking for analyses to run...
326   for (unsigned i = 0; i < AnalysesList.size(); ++i) {
327     enum Ans AnalysisPass = AnalysesList[i];
328
329     for (unsigned j = 0; j < sizeof(AnTable)/sizeof(AnTable[0]); ++j) {
330       if (AnTable[j].AnID == AnalysisPass) {
331         Analyses.add(AnTable[j].PassConstructor());
332         break;                       // get an error later
333       }
334     }
335   }  
336
337   Analyses.run(*CurMod);
338
339   delete CurMod;
340   return 0;
341 }