Chris Lattner | fa6db4b | 2002-01-31 00:46:09 +0000 | [diff] [blame] | 1 | //===----------------------------------------------------------------------===// |
Chris Lattner | 4ec35ab | 2002-04-28 16:21:53 +0000 | [diff] [blame] | 2 | // The LLVM analyze utility |
Chris Lattner | f3dc2c9 | 2001-07-03 15:30:38 +0000 | [diff] [blame] | 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 | // |
Chris Lattner | fa6db4b | 2002-01-31 00:46:09 +0000 | [diff] [blame] | 11 | //===----------------------------------------------------------------------===// |
Chris Lattner | f3dc2c9 | 2001-07-03 15:30:38 +0000 | [diff] [blame] | 12 | |
Chris Lattner | f3dc2c9 | 2001-07-03 15:30:38 +0000 | [diff] [blame] | 13 | #include "llvm/Module.h" |
Chris Lattner | df89f6e | 2001-12-03 17:27:42 +0000 | [diff] [blame] | 14 | #include "llvm/iPHINode.h" |
Chris Lattner | 8bfa89c | 2002-04-08 22:04:24 +0000 | [diff] [blame] | 15 | #include "llvm/Type.h" |
Chris Lattner | fa6db4b | 2002-01-31 00:46:09 +0000 | [diff] [blame] | 16 | #include "llvm/PassManager.h" |
Chris Lattner | f3dc2c9 | 2001-07-03 15:30:38 +0000 | [diff] [blame] | 17 | #include "llvm/Bytecode/Reader.h" |
| 18 | #include "llvm/Assembly/Parser.h" |
Chris Lattner | fa6db4b | 2002-01-31 00:46:09 +0000 | [diff] [blame] | 19 | #include "llvm/Assembly/PrintModulePass.h" |
Chris Lattner | 8bfa89c | 2002-04-08 22:04:24 +0000 | [diff] [blame] | 20 | #include "llvm/Assembly/Writer.h" |
Chris Lattner | b312259 | 2001-09-14 01:42:42 +0000 | [diff] [blame] | 21 | #include "llvm/Analysis/InstForest.h" |
Chris Lattner | 1546bff | 2001-07-20 19:16:29 +0000 | [diff] [blame] | 22 | #include "llvm/Analysis/Expressions.h" |
Chris Lattner | 75deac6 | 2001-11-26 19:18:11 +0000 | [diff] [blame] | 23 | #include "llvm/Analysis/InductionVariable.h" |
Chris Lattner | 221d688 | 2002-02-12 21:07:25 +0000 | [diff] [blame] | 24 | #include "llvm/Support/InstIterator.h" |
Chris Lattner | 9a740fd | 2002-07-27 01:08:50 +0000 | [diff] [blame^] | 25 | #include "llvm/Support/PassNameParser.h" |
Chris Lattner | c4199ec | 2001-09-28 00:07:36 +0000 | [diff] [blame] | 26 | #include <algorithm> |
Chris Lattner | fa6db4b | 2002-01-31 00:46:09 +0000 | [diff] [blame] | 27 | |
Chris Lattner | fa6db4b | 2002-01-31 00:46:09 +0000 | [diff] [blame] | 28 | using std::ostream; |
Chris Lattner | f3dc2c9 | 2001-07-03 15:30:38 +0000 | [diff] [blame] | 29 | |
Chris Lattner | 9a740fd | 2002-07-27 01:08:50 +0000 | [diff] [blame^] | 30 | #if 0 |
Chris Lattner | 1546bff | 2001-07-20 19:16:29 +0000 | [diff] [blame] | 31 | |
Chris Lattner | fa6db4b | 2002-01-31 00:46:09 +0000 | [diff] [blame] | 32 | template <class PassType, class PassName> |
| 33 | class PassPrinter; // Do not implement |
| 34 | |
| 35 | template <class PassName> |
| 36 | class PassPrinter<Pass, PassName> : public Pass { |
Chris Lattner | fa6db4b | 2002-01-31 00:46:09 +0000 | [diff] [blame] | 37 | const AnalysisID ID; |
| 38 | public: |
Chris Lattner | 50e3f88 | 2002-07-22 02:10:07 +0000 | [diff] [blame] | 39 | PassPrinter(AnalysisID id) : ID(id) {} |
Chris Lattner | 96c466b | 2002-04-29 14:57:45 +0000 | [diff] [blame] | 40 | |
| 41 | const char *getPassName() const { return "IP Pass Printer"; } |
Chris Lattner | fa6db4b | 2002-01-31 00:46:09 +0000 | [diff] [blame] | 42 | |
Chris Lattner | 0b12b5f | 2002-06-25 16:13:21 +0000 | [diff] [blame] | 43 | virtual bool run(Module &M) { |
Chris Lattner | bc132d6 | 2002-03-26 22:43:12 +0000 | [diff] [blame] | 44 | printPass(getAnalysis<PassName>(ID), std::cout, M); |
Chris Lattner | fa6db4b | 2002-01-31 00:46:09 +0000 | [diff] [blame] | 45 | return false; |
Chris Lattner | 1546bff | 2001-07-20 19:16:29 +0000 | [diff] [blame] | 46 | } |
Chris Lattner | fa6db4b | 2002-01-31 00:46:09 +0000 | [diff] [blame] | 47 | |
Chris Lattner | f57b845 | 2002-04-27 06:56:12 +0000 | [diff] [blame] | 48 | virtual void getAnalysisUsage(AnalysisUsage &AU) const { |
| 49 | AU.addRequired(ID); |
Chris Lattner | fa6db4b | 2002-01-31 00:46:09 +0000 | [diff] [blame] | 50 | } |
| 51 | }; |
| 52 | |
| 53 | template <class PassName> |
Chris Lattner | f57b845 | 2002-04-27 06:56:12 +0000 | [diff] [blame] | 54 | class PassPrinter<FunctionPass, PassName> : public FunctionPass { |
Chris Lattner | fa6db4b | 2002-01-31 00:46:09 +0000 | [diff] [blame] | 55 | const AnalysisID ID; |
| 56 | public: |
Chris Lattner | 50e3f88 | 2002-07-22 02:10:07 +0000 | [diff] [blame] | 57 | PassPrinter(AnalysisID id) : ID(id) {} |
Chris Lattner | 96c466b | 2002-04-29 14:57:45 +0000 | [diff] [blame] | 58 | |
| 59 | const char *getPassName() const { return "Function Pass Printer"; } |
Chris Lattner | fa6db4b | 2002-01-31 00:46:09 +0000 | [diff] [blame] | 60 | |
Chris Lattner | 0b12b5f | 2002-06-25 16:13:21 +0000 | [diff] [blame] | 61 | virtual bool runOnFunction(Function &F) { |
Chris Lattner | 50e3f88 | 2002-07-22 02:10:07 +0000 | [diff] [blame] | 62 | std::cout << "Running on function '" << F.getName() << "'\n"; |
Chris Lattner | 2fbfdcf | 2002-04-07 20:49:59 +0000 | [diff] [blame] | 63 | printPass(getAnalysis<PassName>(ID), std::cout, F); |
Chris Lattner | fa6db4b | 2002-01-31 00:46:09 +0000 | [diff] [blame] | 64 | return false; |
| 65 | } |
| 66 | |
Chris Lattner | f57b845 | 2002-04-27 06:56:12 +0000 | [diff] [blame] | 67 | virtual void getAnalysisUsage(AnalysisUsage &AU) const { |
| 68 | AU.addRequired(ID); |
Chris Lattner | 97e52e4 | 2002-04-28 21:27:06 +0000 | [diff] [blame] | 69 | AU.setPreservesAll(); |
Chris Lattner | fa6db4b | 2002-01-31 00:46:09 +0000 | [diff] [blame] | 70 | } |
| 71 | }; |
| 72 | |
| 73 | |
Chris Lattner | fbaed2e | 2002-04-29 18:13:31 +0000 | [diff] [blame] | 74 | struct InstForestHelper : public FunctionPass { |
Chris Lattner | 96c466b | 2002-04-29 14:57:45 +0000 | [diff] [blame] | 75 | const char *getPassName() const { return "InstForest Printer"; } |
| 76 | |
Chris Lattner | 0b12b5f | 2002-06-25 16:13:21 +0000 | [diff] [blame] | 77 | void doit(Function &F) { |
| 78 | std::cout << InstForest<char>(&F); |
Chris Lattner | fa6db4b | 2002-01-31 00:46:09 +0000 | [diff] [blame] | 79 | } |
Chris Lattner | 97e52e4 | 2002-04-28 21:27:06 +0000 | [diff] [blame] | 80 | |
| 81 | virtual void getAnalysisUsage(AnalysisUsage &AU) const { |
| 82 | AU.setPreservesAll(); |
| 83 | } |
Chris Lattner | fa6db4b | 2002-01-31 00:46:09 +0000 | [diff] [blame] | 84 | }; |
| 85 | |
Chris Lattner | f57b845 | 2002-04-27 06:56:12 +0000 | [diff] [blame] | 86 | struct IndVars : public FunctionPass { |
Chris Lattner | 96c466b | 2002-04-29 14:57:45 +0000 | [diff] [blame] | 87 | const char *getPassName() const { return "IndVars Printer"; } |
| 88 | |
Chris Lattner | 0b12b5f | 2002-06-25 16:13:21 +0000 | [diff] [blame] | 89 | void doit(Function &F) { |
Chris Lattner | 4ec35ab | 2002-04-28 16:21:53 +0000 | [diff] [blame] | 90 | LoopInfo &LI = getAnalysis<LoopInfo>(); |
Chris Lattner | 2fbfdcf | 2002-04-07 20:49:59 +0000 | [diff] [blame] | 91 | for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) |
Chris Lattner | fa6db4b | 2002-01-31 00:46:09 +0000 | [diff] [blame] | 92 | if (PHINode *PN = dyn_cast<PHINode>(*I)) { |
| 93 | InductionVariable IV(PN, &LI); |
| 94 | if (IV.InductionType != InductionVariable::Unknown) |
Chris Lattner | 9a740fd | 2002-07-27 01:08:50 +0000 | [diff] [blame^] | 95 | IV.print(std::cout); |
Chris Lattner | fa6db4b | 2002-01-31 00:46:09 +0000 | [diff] [blame] | 96 | } |
| 97 | } |
| 98 | |
Chris Lattner | f57b845 | 2002-04-27 06:56:12 +0000 | [diff] [blame] | 99 | void getAnalysisUsage(AnalysisUsage &AU) const { |
Chris Lattner | 4ec35ab | 2002-04-28 16:21:53 +0000 | [diff] [blame] | 100 | AU.addRequired(LoopInfo::ID); |
Chris Lattner | 97e52e4 | 2002-04-28 21:27:06 +0000 | [diff] [blame] | 101 | AU.setPreservesAll(); |
Chris Lattner | fa6db4b | 2002-01-31 00:46:09 +0000 | [diff] [blame] | 102 | } |
| 103 | }; |
| 104 | |
Chris Lattner | f57b845 | 2002-04-27 06:56:12 +0000 | [diff] [blame] | 105 | struct Exprs : public FunctionPass { |
Chris Lattner | 96c466b | 2002-04-29 14:57:45 +0000 | [diff] [blame] | 106 | const char *getPassName() const { return "Expression Printer"; } |
| 107 | |
Chris Lattner | 0b12b5f | 2002-06-25 16:13:21 +0000 | [diff] [blame] | 108 | static void doit(Function &F) { |
| 109 | std::cout << "Classified expressions for: " << F.getName() << "\n"; |
Chris Lattner | 2fbfdcf | 2002-04-07 20:49:59 +0000 | [diff] [blame] | 110 | for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) { |
Chris Lattner | bc132d6 | 2002-03-26 22:43:12 +0000 | [diff] [blame] | 111 | std::cout << *I; |
Chris Lattner | fa6db4b | 2002-01-31 00:46:09 +0000 | [diff] [blame] | 112 | |
| 113 | if ((*I)->getType() == Type::VoidTy) continue; |
| 114 | analysis::ExprType R = analysis::ClassifyExpression(*I); |
| 115 | if (R.Var == *I) continue; // Doesn't tell us anything |
| 116 | |
Chris Lattner | bc132d6 | 2002-03-26 22:43:12 +0000 | [diff] [blame] | 117 | std::cout << "\t\tExpr ="; |
Chris Lattner | fa6db4b | 2002-01-31 00:46:09 +0000 | [diff] [blame] | 118 | switch (R.ExprTy) { |
| 119 | case analysis::ExprType::ScaledLinear: |
Chris Lattner | bc132d6 | 2002-03-26 22:43:12 +0000 | [diff] [blame] | 120 | WriteAsOperand(std::cout << "(", (Value*)R.Scale) << " ) *"; |
Chris Lattner | fa6db4b | 2002-01-31 00:46:09 +0000 | [diff] [blame] | 121 | // fall through |
| 122 | case analysis::ExprType::Linear: |
Chris Lattner | bc132d6 | 2002-03-26 22:43:12 +0000 | [diff] [blame] | 123 | WriteAsOperand(std::cout << "(", R.Var) << " )"; |
Chris Lattner | fa6db4b | 2002-01-31 00:46:09 +0000 | [diff] [blame] | 124 | if (R.Offset == 0) break; |
Chris Lattner | bc132d6 | 2002-03-26 22:43:12 +0000 | [diff] [blame] | 125 | else std::cout << " +"; |
Chris Lattner | fa6db4b | 2002-01-31 00:46:09 +0000 | [diff] [blame] | 126 | // fall through |
| 127 | case analysis::ExprType::Constant: |
Chris Lattner | bc132d6 | 2002-03-26 22:43:12 +0000 | [diff] [blame] | 128 | if (R.Offset) WriteAsOperand(std::cout, (Value*)R.Offset); |
| 129 | else std::cout << " 0"; |
Chris Lattner | fa6db4b | 2002-01-31 00:46:09 +0000 | [diff] [blame] | 130 | break; |
| 131 | } |
Chris Lattner | bc132d6 | 2002-03-26 22:43:12 +0000 | [diff] [blame] | 132 | std::cout << "\n\n"; |
Chris Lattner | df89f6e | 2001-12-03 17:27:42 +0000 | [diff] [blame] | 133 | } |
Chris Lattner | fa6db4b | 2002-01-31 00:46:09 +0000 | [diff] [blame] | 134 | } |
Chris Lattner | 97e52e4 | 2002-04-28 21:27:06 +0000 | [diff] [blame] | 135 | virtual void getAnalysisUsage(AnalysisUsage &AU) const { |
| 136 | AU.setPreservesAll(); |
| 137 | } |
Chris Lattner | fa6db4b | 2002-01-31 00:46:09 +0000 | [diff] [blame] | 138 | }; |
Chris Lattner | 9a740fd | 2002-07-27 01:08:50 +0000 | [diff] [blame^] | 139 | #endif |
Chris Lattner | 75deac6 | 2001-11-26 19:18:11 +0000 | [diff] [blame] | 140 | |
Chris Lattner | 9a740fd | 2002-07-27 01:08:50 +0000 | [diff] [blame^] | 141 | struct ModulePassPrinter : public Pass { |
| 142 | Pass *PassToPrint; |
| 143 | ModulePassPrinter(Pass *PI) : PassToPrint(PI) {} |
Chris Lattner | 75deac6 | 2001-11-26 19:18:11 +0000 | [diff] [blame] | 144 | |
Chris Lattner | 9a740fd | 2002-07-27 01:08:50 +0000 | [diff] [blame^] | 145 | virtual bool run(Module &M) { |
| 146 | std::cout << "Printing Analysis info for Pass " |
| 147 | << PassToPrint->getPassName() << ":\n"; |
| 148 | PassToPrint->print(std::cout, &M); |
| 149 | |
| 150 | // Get and print pass... |
Chris Lattner | fa6db4b | 2002-01-31 00:46:09 +0000 | [diff] [blame] | 151 | return false; |
| 152 | } |
| 153 | }; |
| 154 | |
Chris Lattner | 9a740fd | 2002-07-27 01:08:50 +0000 | [diff] [blame^] | 155 | struct FunctionPassPrinter : public FunctionPass { |
| 156 | const PassInfo *PassToPrint; |
| 157 | FunctionPassPrinter(const PassInfo *PI) : PassToPrint(PI) {} |
Chris Lattner | fa6db4b | 2002-01-31 00:46:09 +0000 | [diff] [blame] | 158 | |
Chris Lattner | 9a740fd | 2002-07-27 01:08:50 +0000 | [diff] [blame^] | 159 | virtual bool runOnFunction(Function &F) { |
| 160 | std::cout << "Printing Analysis info for function '" << F.getName() |
| 161 | << "': Pass " << PassToPrint->getPassName() << ":\n"; |
| 162 | getAnalysis<Pass>(PassToPrint).print(std::cout, F.getParent()); |
Chris Lattner | c13aff6 | 2001-07-06 16:59:10 +0000 | [diff] [blame] | 163 | |
Chris Lattner | 9a740fd | 2002-07-27 01:08:50 +0000 | [diff] [blame^] | 164 | // Get and print pass... |
| 165 | return false; |
| 166 | } |
Chris Lattner | c13aff6 | 2001-07-06 16:59:10 +0000 | [diff] [blame] | 167 | |
Chris Lattner | 9a740fd | 2002-07-27 01:08:50 +0000 | [diff] [blame^] | 168 | virtual void getAnalysisUsage(AnalysisUsage &AU) const { |
| 169 | AU.addRequired(PassToPrint); |
| 170 | AU.setPreservesAll(); |
| 171 | } |
Chris Lattner | 8f367bd | 2001-07-23 02:35:57 +0000 | [diff] [blame] | 172 | }; |
| 173 | |
Chris Lattner | 9a740fd | 2002-07-27 01:08:50 +0000 | [diff] [blame^] | 174 | struct BasicBlockPassPrinter : public BasicBlockPass { |
| 175 | const PassInfo *PassToPrint; |
| 176 | BasicBlockPassPrinter(const PassInfo *PI) : PassToPrint(PI) {} |
| 177 | |
| 178 | virtual bool runOnBasicBlock(BasicBlock &BB) { |
| 179 | std::cout << "Printing Analysis info for BasicBlock '" << BB.getName() |
| 180 | << "': Pass " << PassToPrint->getPassName() << ":\n"; |
| 181 | getAnalysis<Pass>(PassToPrint).print(std::cout, BB.getParent()->getParent()); |
| 182 | |
| 183 | // Get and print pass... |
| 184 | return false; |
| 185 | } |
| 186 | |
| 187 | virtual void getAnalysisUsage(AnalysisUsage &AU) const { |
| 188 | AU.addRequired(PassToPrint); |
| 189 | AU.setPreservesAll(); |
| 190 | } |
| 191 | }; |
| 192 | |
| 193 | |
| 194 | |
| 195 | |
Chris Lattner | 98ad7e9 | 2002-07-25 16:31:01 +0000 | [diff] [blame] | 196 | static cl::opt<std::string> |
Chris Lattner | 50e3f88 | 2002-07-22 02:10:07 +0000 | [diff] [blame] | 197 | InputFilename(cl::Positional, cl::desc("<input file>"), cl::init("-"), |
| 198 | cl::value_desc("filename")); |
| 199 | |
| 200 | static cl::opt<bool> Quiet("q", cl::desc("Don't print analysis pass names")); |
| 201 | static cl::alias QuietA("quiet", cl::desc("Alias for -q"), |
| 202 | cl::aliasopt(Quiet)); |
| 203 | |
Chris Lattner | 9a740fd | 2002-07-27 01:08:50 +0000 | [diff] [blame^] | 204 | // The AnalysesList is automatically populated with registered Passes by the |
| 205 | // PassNameParser. |
| 206 | // |
| 207 | static cl::list<const PassInfo*, bool, |
| 208 | FilteredPassNameParser<PassInfo::Analysis> > |
| 209 | AnalysesList(cl::desc("Analyses available:")); |
Chris Lattner | fa6db4b | 2002-01-31 00:46:09 +0000 | [diff] [blame] | 210 | |
Chris Lattner | f3dc2c9 | 2001-07-03 15:30:38 +0000 | [diff] [blame] | 211 | |
| 212 | int main(int argc, char **argv) { |
Chris Lattner | 8f367bd | 2001-07-23 02:35:57 +0000 | [diff] [blame] | 213 | cl::ParseCommandLineOptions(argc, argv, " llvm analysis printer tool\n"); |
Chris Lattner | f3dc2c9 | 2001-07-03 15:30:38 +0000 | [diff] [blame] | 214 | |
Chris Lattner | bc132d6 | 2002-03-26 22:43:12 +0000 | [diff] [blame] | 215 | Module *CurMod = 0; |
Chris Lattner | 7d92262 | 2002-02-01 05:09:35 +0000 | [diff] [blame] | 216 | try { |
Chris Lattner | bc132d6 | 2002-03-26 22:43:12 +0000 | [diff] [blame] | 217 | CurMod = ParseBytecodeFile(InputFilename); |
| 218 | if (!CurMod && !(CurMod = ParseAssemblyFile(InputFilename))){ |
Chris Lattner | 7d92262 | 2002-02-01 05:09:35 +0000 | [diff] [blame] | 219 | std::cerr << "Input file didn't read correctly.\n"; |
| 220 | return 1; |
| 221 | } |
| 222 | } catch (const ParseException &E) { |
Chris Lattner | 5b077b0 | 2002-02-24 23:25:24 +0000 | [diff] [blame] | 223 | std::cerr << E.getMessage() << "\n"; |
Chris Lattner | c13aff6 | 2001-07-06 16:59:10 +0000 | [diff] [blame] | 224 | return 1; |
Chris Lattner | f3dc2c9 | 2001-07-03 15:30:38 +0000 | [diff] [blame] | 225 | } |
| 226 | |
Chris Lattner | fa6db4b | 2002-01-31 00:46:09 +0000 | [diff] [blame] | 227 | // Create a PassManager to hold and optimize the collection of passes we are |
| 228 | // about to build... |
| 229 | // |
Chris Lattner | 9a740fd | 2002-07-27 01:08:50 +0000 | [diff] [blame^] | 230 | PassManager Passes; |
Chris Lattner | fa6db4b | 2002-01-31 00:46:09 +0000 | [diff] [blame] | 231 | |
Chris Lattner | 9a740fd | 2002-07-27 01:08:50 +0000 | [diff] [blame^] | 232 | // Create a new optimization pass for each one specified on the command line |
Chris Lattner | c4199ec | 2001-09-28 00:07:36 +0000 | [diff] [blame] | 233 | for (unsigned i = 0; i < AnalysesList.size(); ++i) { |
Chris Lattner | 9a740fd | 2002-07-27 01:08:50 +0000 | [diff] [blame^] | 234 | const PassInfo *Analysis = AnalysesList[i]; |
| 235 | |
| 236 | if (Analysis->getNormalCtor()) { |
| 237 | Pass *P = Analysis->getNormalCtor()(); |
| 238 | Passes.add(P); |
Chris Lattner | c4199ec | 2001-09-28 00:07:36 +0000 | [diff] [blame] | 239 | |
Chris Lattner | 9a740fd | 2002-07-27 01:08:50 +0000 | [diff] [blame^] | 240 | if (BasicBlockPass *BBP = dynamic_cast<BasicBlockPass*>(P)) |
| 241 | Passes.add(new BasicBlockPassPrinter(Analysis)); |
| 242 | else if (FunctionPass *FP = dynamic_cast<FunctionPass*>(P)) |
| 243 | Passes.add(new FunctionPassPrinter(Analysis)); |
| 244 | else |
| 245 | Passes.add(new ModulePassPrinter(P)); |
Chris Lattner | c4199ec | 2001-09-28 00:07:36 +0000 | [diff] [blame] | 246 | |
Chris Lattner | 9a740fd | 2002-07-27 01:08:50 +0000 | [diff] [blame^] | 247 | } else |
| 248 | cerr << "Cannot create pass: " << Analysis->getPassName() << "\n"; |
| 249 | } |
| 250 | |
| 251 | Passes.run(*CurMod); |
Chris Lattner | f3dc2c9 | 2001-07-03 15:30:38 +0000 | [diff] [blame] | 252 | |
Chris Lattner | bc132d6 | 2002-03-26 22:43:12 +0000 | [diff] [blame] | 253 | delete CurMod; |
Chris Lattner | f3dc2c9 | 2001-07-03 15:30:38 +0000 | [diff] [blame] | 254 | return 0; |
| 255 | } |