Add hooks to print natural loop information and induction variables
[oota-llvm.git] / tools / analyze / analyze.cpp
1 //===------------------------------------------------------------------------===
2 // 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/Instruction.h"
14 #include "llvm/Module.h"
15 #include "llvm/Method.h"
16 #include "llvm/Bytecode/Reader.h"
17 #include "llvm/Assembly/Parser.h"
18 #include "llvm/Support/CommandLine.h"
19 #include "llvm/Analysis/Writer.h"
20
21 #include "llvm/Analysis/InstForest.h"
22 #include "llvm/Analysis/Dominators.h"
23 #include "llvm/Analysis/IntervalPartition.h"
24 #include "llvm/Analysis/Expressions.h"
25 #include "llvm/Analysis/InductionVariable.h"
26 #include "llvm/Analysis/CallGraph.h"
27 #include "llvm/Analysis/LoopInfo.h"
28 #include "llvm/Analysis/FindUnsafePointerTypes.h"
29 #include "llvm/Analysis/FindUsedTypes.h"
30 #include <algorithm>
31
32 static void PrintMethod(Method *M) {
33   cout << M;
34 }
35
36 static void PrintIntervalPartition(Method *M) {
37   cout << cfg::IntervalPartition(M);
38 }
39
40 static void PrintClassifiedExprs(Method *M) {
41   cout << "Classified expressions for: " << M->getName() << endl;
42   Method::inst_iterator I = M->inst_begin(), E = M->inst_end();
43   for (; I != E; ++I) {
44     cout << *I;
45
46     if ((*I)->getType() == Type::VoidTy) continue;
47     analysis::ExprType R = analysis::ClassifyExpression(*I);
48     if (R.Var == *I) continue;  // Doesn't tell us anything
49
50     cout << "\t\tExpr =";
51     switch (R.ExprTy) {
52     case analysis::ExprType::ScaledLinear:
53       WriteAsOperand(cout << "(", (Value*)R.Scale) << " ) *";
54       // fall through
55     case analysis::ExprType::Linear:
56       WriteAsOperand(cout << "(", R.Var) << " )";
57       if (R.Offset == 0) break;
58       else cout << " +";
59       // fall through
60     case analysis::ExprType::Constant:
61       if (R.Offset) WriteAsOperand(cout, (Value*)R.Offset); else cout << " 0";
62       break;
63     }
64     cout << endl << endl;
65   }
66 }
67
68 static void PrintInductionVariables(Method *M) {
69   cfg::LoopInfo LI(M);
70   for (Method::inst_iterator I = M->inst_begin(), E = M->inst_end();
71        I != E; ++I) {
72     InductionVariable IV(*I, &LI);
73     if (IV.InductionType != InductionVariable::Unknown)
74       cout << IV;
75   }
76 }
77
78
79 static void PrintInstForest(Method *M) {
80   cout << analysis::InstForest<char>(M);
81 }
82 static void PrintLoops(Method *M) {
83   cout << cfg::LoopInfo(M);
84 }
85 static void PrintCallGraph(Module *M) {
86   cout << cfg::CallGraph(M);
87 }
88
89 static void PrintUnsafePtrTypes(Module *M) {
90   FindUnsafePointerTypes FUPT;
91   FUPT.run(M);
92   FUPT.printResults(M, cout);
93 }
94
95 static void PrintUsedTypes(Module *M) {
96   FindUsedTypes FUT;
97   FUT.run(M);
98   FUT.printTypes(cout, M);
99 }
100
101 static void PrintDominatorSets(Method *M) {
102   cout << cfg::DominatorSet(M);
103 }
104 static void PrintImmediateDominators(Method *M) {
105   cout << cfg::ImmediateDominators(M);
106 }
107 static void PrintDominatorTree(Method *M) {
108   cout << cfg::DominatorTree(M);
109 }
110 static void PrintDominanceFrontier(Method *M) {
111   cout << cfg::DominanceFrontier(M);
112 }
113
114 static void PrintPostDominatorSets(Method *M) {
115   cout << cfg::DominatorSet(M, true);
116 }
117 static void PrintImmediatePostDoms(Method *M) {
118   cout << cfg::ImmediateDominators(cfg::DominatorSet(M, true));
119 }
120 static void PrintPostDomTree(Method *M) {
121   cout << cfg::DominatorTree(cfg::DominatorSet(M, true));
122 }
123 static void PrintPostDomFrontier(Method *M) {
124   cout << cfg::DominanceFrontier(cfg::DominatorSet(M, true));
125 }
126
127
128 enum Ans {
129   PassDone,   // Unique Marker
130   print, intervals, exprclassify, instforest, loops, indvars, callgraph,
131   printusedtypes, unsafepointertypes,
132
133   domset, idom, domtree, domfrontier,
134   postdomset, postidom, postdomtree, postdomfrontier,
135 };
136
137 cl::String InputFilename ("", "Load <arg> file to analyze", cl::NoFlags, "-");
138 cl::Flag   Quiet         ("q", "Don't print analysis pass names");
139 cl::Alias  QuietA        ("quiet", "Alias for -q", cl::NoFlags, Quiet);
140 cl::EnumList<enum Ans> AnalysesList(cl::NoFlags,
141   clEnumVal(print          , "Print each Method"),
142   clEnumVal(intervals      , "Print Interval Partitions"),
143   clEnumVal(exprclassify   , "Classify Expressions"),
144   clEnumVal(instforest     , "Print Instruction Forest"),
145   clEnumVal(loops          , "Print Loops"),
146   clEnumVal(indvars        , "Print Induction Variables"),
147   clEnumVal(callgraph      , "Print Call Graph"),
148   clEnumVal(printusedtypes , "Print Types Used by Module"),
149   clEnumVal(unsafepointertypes, "Print Unsafe Pointer Types"),
150
151   clEnumVal(domset         , "Print Dominator Sets"),
152   clEnumVal(idom           , "Print Immediate Dominators"),
153   clEnumVal(domtree        , "Print Dominator Tree"),
154   clEnumVal(domfrontier    , "Print Dominance Frontier"),
155
156   clEnumVal(postdomset     , "Print Postdominator Sets"),
157   clEnumVal(postidom       , "Print Immediate Postdominators"),
158   clEnumVal(postdomtree    , "Print Post Dominator Tree"),
159   clEnumVal(postdomfrontier, "Print Postdominance Frontier"),
160 0);
161
162 struct {
163   enum Ans AnID;
164   void (*AnPtr)(Method *M);
165 } MethAnTable[] = {
166   { print          , PrintMethod              },
167   { intervals      , PrintIntervalPartition   },
168   { exprclassify   , PrintClassifiedExprs     },
169   { instforest     , PrintInstForest          },
170   { loops          , PrintLoops               },
171   { indvars        , PrintInductionVariables  },
172
173   { domset         , PrintDominatorSets       },
174   { idom           , PrintImmediateDominators },
175   { domtree        , PrintDominatorTree       },
176   { domfrontier    , PrintDominanceFrontier   },
177
178   { postdomset     , PrintPostDominatorSets   },
179   { postidom       , PrintImmediatePostDoms   },
180   { postdomtree    , PrintPostDomTree         },
181   { postdomfrontier, PrintPostDomFrontier     },
182 };
183
184 pair<enum Ans, void (*)(Module *)> ModAnTable[] = {
185   pair<enum Ans, void (*)(Module *)>(callgraph         , PrintCallGraph),
186   pair<enum Ans, void (*)(Module *)>(printusedtypes    , PrintUsedTypes),
187   pair<enum Ans, void (*)(Module *)>(unsafepointertypes, PrintUnsafePtrTypes),
188 };
189
190
191
192 int main(int argc, char **argv) {
193   cl::ParseCommandLineOptions(argc, argv, " llvm analysis printer tool\n");
194
195   Module *C = ParseBytecodeFile(InputFilename);
196   if (!C && !(C = ParseAssemblyFile(InputFilename))) {
197     cerr << "Input file didn't read correctly.\n";
198     return 1;
199   }
200
201   // Loop over all of the analyses looking for module level analyses to run...
202   for (unsigned i = 0; i < AnalysesList.size(); ++i) {
203     enum Ans AnalysisPass = AnalysesList[i];
204
205     for (unsigned j = 0; j < sizeof(ModAnTable)/sizeof(ModAnTable[0]); ++j) {
206       if (ModAnTable[j].first == AnalysisPass) {
207         if (!Quiet)
208           cerr << "Running: " << AnalysesList.getArgDescription(AnalysisPass) 
209                << " analysis on module!\n";
210         ModAnTable[j].second(C);
211         AnalysesList[i] = PassDone;  // Mark pass as complete so that we don't
212         break;                       // get an error later
213       }
214     }
215   }  
216
217   // Loop over all of the methods in the module...
218   for (Module::iterator I = C->begin(), E = C->end(); I != E; ++I) {
219     Method *M = *I;
220     if (M->isExternal()) continue;
221
222     for (unsigned i = 0; i < AnalysesList.size(); ++i) {
223       enum Ans AnalysisPass = AnalysesList[i];
224       if (AnalysisPass == PassDone) continue;  // Don't rerun module analyses
225
226       // Loop over all of the analyses to be run...
227       unsigned j;
228       for (j = 0; j < sizeof(MethAnTable)/sizeof(MethAnTable[0]); ++j) {
229         if (AnalysisPass == MethAnTable[j].AnID) {
230           if (!Quiet)
231             cerr << "Running: " << AnalysesList.getArgDescription(AnalysisPass) 
232                  << " analysis on '" << ((Value*)M)->getName() << "'!\n";
233           MethAnTable[j].AnPtr(M);
234           break;
235         }
236       }
237       if (j == sizeof(MethAnTable)/sizeof(MethAnTable[0])) 
238         cerr << "Analysis tables inconsistent!\n";
239     }
240   }
241
242   delete C;
243   return 0;
244 }