f22f7346c3c90fdf62762336149b7de96fe033d7
[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 string Message;
83   const AnalysisID ID;
84 public:
85   PassPrinter(const string &M, AnalysisID id) : Message(M), ID(id) {}
86
87   const char *getPassName() const { return "IP Pass Printer"; }
88   
89   virtual bool run(Module &M) {
90     std::cout << Message << "\n";
91     printPass(getAnalysis<PassName>(ID), std::cout, M);
92     return false;
93   }
94
95   virtual void getAnalysisUsage(AnalysisUsage &AU) const {
96     AU.addRequired(ID);
97   }
98 };
99
100 template <class PassName>
101 class PassPrinter<FunctionPass, PassName> : public FunctionPass {
102   const string Message;
103   const AnalysisID ID;
104 public:
105   PassPrinter(const string &M, AnalysisID id) : Message(M), ID(id) {}
106
107     const char *getPassName() const { return "Function Pass Printer"; }
108   
109   virtual bool runOnFunction(Function &F) {
110     std::cout << Message << " on function '" << F.getName() << "'\n";
111     printPass(getAnalysis<PassName>(ID), std::cout, F);
112     return false;
113   }
114
115   virtual void getAnalysisUsage(AnalysisUsage &AU) const {
116     AU.addRequired(ID);
117     AU.setPreservesAll();
118   }
119 };
120
121
122
123 template <class PassType, class PassName, AnalysisID &ID>
124 Pass *New(const string &Message) {
125   return new PassPrinter<PassType, PassName>(Message, ID);
126 }
127 template <class PassType, class PassName>
128 Pass *New(const string &Message) {
129   return new PassPrinter<PassType, PassName>(Message, PassName::ID);
130 }
131
132
133 Pass *createPrintFunctionPass(const string &Message) {
134   return new PrintFunctionPass(Message, &std::cout);
135 }
136 Pass *createPrintModulePass(const string &Message) {
137   return new PrintModulePass(&std::cout);
138 }
139
140 struct InstForestHelper : public FunctionPass {
141   const char *getPassName() const { return "InstForest Printer"; }
142
143   void doit(Function &F) {
144     std::cout << InstForest<char>(&F);
145   }
146
147   virtual void getAnalysisUsage(AnalysisUsage &AU) const {
148     AU.setPreservesAll();
149   }
150 };
151
152 struct IndVars : public FunctionPass {
153   const char *getPassName() const { return "IndVars Printer"; }
154
155   void doit(Function &F) {
156     LoopInfo &LI = getAnalysis<LoopInfo>();
157     for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I)
158       if (PHINode *PN = dyn_cast<PHINode>(*I)) {
159         InductionVariable IV(PN, &LI);
160         if (IV.InductionType != InductionVariable::Unknown)
161           std::cout << IV;
162       }
163   }
164
165   void getAnalysisUsage(AnalysisUsage &AU) const {
166     AU.addRequired(LoopInfo::ID);
167     AU.setPreservesAll();
168   }
169 };
170
171 struct Exprs : public FunctionPass {
172   const char *getPassName() const { return "Expression Printer"; }
173
174   static void doit(Function &F) {
175     std::cout << "Classified expressions for: " << F.getName() << "\n";
176     for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) {
177       std::cout << *I;
178       
179       if ((*I)->getType() == Type::VoidTy) continue;
180       analysis::ExprType R = analysis::ClassifyExpression(*I);
181       if (R.Var == *I) continue;  // Doesn't tell us anything
182       
183       std::cout << "\t\tExpr =";
184       switch (R.ExprTy) {
185       case analysis::ExprType::ScaledLinear:
186         WriteAsOperand(std::cout << "(", (Value*)R.Scale) << " ) *";
187         // fall through
188       case analysis::ExprType::Linear:
189         WriteAsOperand(std::cout << "(", R.Var) << " )";
190         if (R.Offset == 0) break;
191         else std::cout << " +";
192         // fall through
193       case analysis::ExprType::Constant:
194         if (R.Offset) WriteAsOperand(std::cout, (Value*)R.Offset);
195         else std::cout << " 0";
196         break;
197       }
198       std::cout << "\n\n";
199     }
200   }
201   virtual void getAnalysisUsage(AnalysisUsage &AU) const {
202     AU.setPreservesAll();
203   }
204 };
205
206
207 template<class TraitClass>
208 class PrinterPass : public TraitClass {
209   const string Message;
210 public:
211   PrinterPass(const string &M) : Message(M) {}
212
213   virtual bool runOnFunction(Function &F) {
214     std::cout << Message << " on function '" << F.getName() << "'\n";
215
216     TraitClass::doit(F);
217     return false;
218   }
219 };
220
221
222 template<class PassClass>
223 Pass *Create(const string &Message) {
224   return new PassClass(Message);
225 }
226
227
228
229 enum Ans {
230   // global analyses
231   print, intervals, exprs, instforest, loops, indvars,
232
233   // ip analyses
234   printmodule, callgraph, datastructure, budatastructure,
235   printusedtypes, unsafepointertypes,
236
237   domset, idom, domtree, domfrontier,
238   postdomset, postidom, postdomtree, postdomfrontier,
239 };
240
241 cl::String InputFilename ("", "Load <arg> file to analyze", cl::NoFlags, "-");
242 cl::Flag   Quiet         ("q", "Don't print analysis pass names");
243 cl::Alias  QuietA        ("quiet", "Alias for -q", cl::NoFlags, Quiet);
244 cl::EnumList<enum Ans> AnalysesList(cl::NoFlags,
245   clEnumVal(print          , "Print each function"),
246   clEnumVal(intervals      , "Print Interval Partitions"),
247   clEnumVal(exprs          , "Classify Expressions"),
248   clEnumVal(instforest     , "Print Instruction Forest"),
249   clEnumVal(loops          , "Print natural loops"),
250   clEnumVal(indvars        , "Print Induction Variables"),
251
252   clEnumVal(printmodule    , "Print entire module"),
253   clEnumVal(callgraph      , "Print Call Graph"),
254   clEnumVal(datastructure  , "Print data structure information"),
255   clEnumVal(budatastructure, "Print bottom-up data structure information"),
256   clEnumVal(printusedtypes , "Print types used by module"),
257   clEnumVal(unsafepointertypes, "Print unsafe pointer types"),
258
259   clEnumVal(domset         , "Print Dominator Sets"),
260   clEnumVal(idom           , "Print Immediate Dominators"),
261   clEnumVal(domtree        , "Print Dominator Tree"),
262   clEnumVal(domfrontier    , "Print Dominance Frontier"),
263
264   clEnumVal(postdomset     , "Print Postdominator Sets"),
265   clEnumVal(postidom       , "Print Immediate Postdominators"),
266   clEnumVal(postdomtree    , "Print Post Dominator Tree"),
267   clEnumVal(postdomfrontier, "Print Postdominance Frontier"),
268 0);
269
270
271 struct {
272   enum Ans AnID;
273   Pass *(*PassConstructor)(const string &Message);
274 } AnTable[] = {
275   // Global analyses
276   { print             , createPrintFunctionPass                 },
277   { intervals         , New<FunctionPass, IntervalPartition>    },
278   { loops             , New<FunctionPass, LoopInfo>             },
279   { instforest        , Create<PrinterPass<InstForestHelper> >  },
280   { indvars           , Create<PrinterPass<IndVars> >           },
281   { exprs             , Create<PrinterPass<Exprs> >             },
282
283   // IP Analyses...
284   { printmodule       , createPrintModulePass             },
285   { printusedtypes    , New<Pass, FindUsedTypes>          },
286   { callgraph         , New<Pass, CallGraph>              },
287   { datastructure     , New<Pass, LocalDataStructures>    },
288   { budatastructure   , New<Pass, BUDataStructures>       },
289   { unsafepointertypes, New<Pass, FindUnsafePointerTypes> },
290
291   // Dominator analyses
292   { domset            , New<FunctionPass, DominatorSet>        },
293   { idom              , New<FunctionPass, ImmediateDominators> },
294   { domtree           , New<FunctionPass, DominatorTree>       },
295   { domfrontier       , New<FunctionPass, DominanceFrontier>   },
296
297   { postdomset        , New<FunctionPass, DominatorSet, DominatorSet::PostDomID> },
298   { postidom          , New<FunctionPass, ImmediateDominators, ImmediateDominators::PostDomID> },
299   { postdomtree       , New<FunctionPass, DominatorTree, DominatorTree::PostDomID> },
300   { postdomfrontier   , New<FunctionPass, DominanceFrontier, DominanceFrontier::PostDomID> },
301 };
302
303 int main(int argc, char **argv) {
304   cl::ParseCommandLineOptions(argc, argv, " llvm analysis printer tool\n");
305
306   Module *CurMod = 0;
307   try {
308     CurMod = ParseBytecodeFile(InputFilename);
309     if (!CurMod && !(CurMod = ParseAssemblyFile(InputFilename))){
310       std::cerr << "Input file didn't read correctly.\n";
311       return 1;
312     }
313   } catch (const ParseException &E) {
314     std::cerr << E.getMessage() << "\n";
315     return 1;
316   }
317
318   // Create a PassManager to hold and optimize the collection of passes we are
319   // about to build...
320   //
321   PassManager Analyses;
322
323   // Loop over all of the analyses looking for analyses to run...
324   for (unsigned i = 0; i < AnalysesList.size(); ++i) {
325     enum Ans AnalysisPass = AnalysesList[i];
326
327     for (unsigned j = 0; j < sizeof(AnTable)/sizeof(AnTable[0]); ++j) {
328       if (AnTable[j].AnID == AnalysisPass) {
329         string Message;
330         if (!Quiet)
331           Message = "\nRunning: '" + 
332             string(AnalysesList.getArgDescription(AnalysisPass)) + "' analysis";
333         Analyses.add(AnTable[j].PassConstructor(Message));
334         break;                       // get an error later
335       }
336     }
337   }  
338
339   Analyses.run(*CurMod);
340
341   delete CurMod;
342   return 0;
343 }