| Chris Lattner | 6f82d07 | 2003-10-28 19:16:35 +0000 | [diff] [blame] | 1 | //===- llvm-prof.cpp - Read in and process llvmprof.out data files --------===// | 
|  | 2 | // | 
|  | 3 | //                      The LLVM Compiler Infrastructure | 
|  | 4 | // | 
|  | 5 | // This file was developed by the LLVM research group and is distributed under | 
|  | 6 | // the University of Illinois Open Source License. See LICENSE.TXT for details. | 
|  | 7 | // | 
|  | 8 | //===----------------------------------------------------------------------===// | 
|  | 9 | // | 
|  | 10 | // This tools is meant for use with the various LLVM profiling instrumentation | 
|  | 11 | // passes.  It reads in the data file produced by executing an instrumented | 
|  | 12 | // program, and outputs a nice report. | 
|  | 13 | // | 
|  | 14 | //===----------------------------------------------------------------------===// | 
|  | 15 |  | 
| Chris Lattner | 8c2730e | 2004-03-08 20:04:32 +0000 | [diff] [blame] | 16 | #include "llvm/InstrTypes.h" | 
| Chris Lattner | 5e71764 | 2003-10-30 23:42:09 +0000 | [diff] [blame] | 17 | #include "llvm/Module.h" | 
|  | 18 | #include "llvm/Assembly/AsmAnnotationWriter.h" | 
| Chris Lattner | 89cf393 | 2004-02-11 05:56:07 +0000 | [diff] [blame] | 19 | #include "llvm/Analysis/ProfileInfoLoader.h" | 
| Chris Lattner | 6f82d07 | 2003-10-28 19:16:35 +0000 | [diff] [blame] | 20 | #include "llvm/Bytecode/Reader.h" | 
|  | 21 | #include "Support/CommandLine.h" | 
| Chris Lattner | bed85ff | 2004-05-27 05:41:36 +0000 | [diff] [blame] | 22 | #include "llvm/System/Signals.h" | 
| Chris Lattner | 7a78d81 | 2003-10-28 21:08:18 +0000 | [diff] [blame] | 23 | #include <cstdio> | 
| Reid Spencer | 86f42bd | 2004-07-04 12:20:55 +0000 | [diff] [blame] | 24 | #include <iostream> | 
| Chris Lattner | 33f1ca7 | 2003-10-28 21:25:23 +0000 | [diff] [blame] | 25 | #include <map> | 
| Chris Lattner | 5e71764 | 2003-10-30 23:42:09 +0000 | [diff] [blame] | 26 | #include <set> | 
| Chris Lattner | 6f82d07 | 2003-10-28 19:16:35 +0000 | [diff] [blame] | 27 |  | 
| Brian Gaeke | d0fde30 | 2003-11-11 22:41:34 +0000 | [diff] [blame] | 28 | using namespace llvm; | 
|  | 29 |  | 
| Chris Lattner | 6f82d07 | 2003-10-28 19:16:35 +0000 | [diff] [blame] | 30 | namespace { | 
|  | 31 | cl::opt<std::string> | 
|  | 32 | BytecodeFile(cl::Positional, cl::desc("<program bytecode file>"), | 
|  | 33 | cl::Required); | 
|  | 34 |  | 
|  | 35 | cl::opt<std::string> | 
|  | 36 | ProfileDataFile(cl::Positional, cl::desc("<llvmprof.out file>"), | 
|  | 37 | cl::Optional, cl::init("llvmprof.out")); | 
| Chris Lattner | 5e71764 | 2003-10-30 23:42:09 +0000 | [diff] [blame] | 38 |  | 
|  | 39 | cl::opt<bool> | 
|  | 40 | PrintAnnotatedLLVM("annotated-llvm", | 
|  | 41 | cl::desc("Print LLVM code with frequency annotations")); | 
|  | 42 | cl::alias PrintAnnotated2("A", cl::desc("Alias for --annotated-llvm"), | 
|  | 43 | cl::aliasopt(PrintAnnotatedLLVM)); | 
| Chris Lattner | cde1cf3 | 2003-11-06 20:29:25 +0000 | [diff] [blame] | 44 | cl::opt<bool> | 
|  | 45 | PrintAllCode("print-all-code", | 
|  | 46 | cl::desc("Print annotated code for the entire program")); | 
| Chris Lattner | 6f82d07 | 2003-10-28 19:16:35 +0000 | [diff] [blame] | 47 | } | 
|  | 48 |  | 
| Chris Lattner | 7a78d81 | 2003-10-28 21:08:18 +0000 | [diff] [blame] | 49 | // PairSecondSort - A sorting predicate to sort by the second element of a pair. | 
|  | 50 | template<class T> | 
| Chris Lattner | 18884a8 | 2003-10-29 21:41:17 +0000 | [diff] [blame] | 51 | struct PairSecondSortReverse | 
| Chris Lattner | 7a78d81 | 2003-10-28 21:08:18 +0000 | [diff] [blame] | 52 | : public std::binary_function<std::pair<T, unsigned>, | 
|  | 53 | std::pair<T, unsigned>, bool> { | 
|  | 54 | bool operator()(const std::pair<T, unsigned> &LHS, | 
|  | 55 | const std::pair<T, unsigned> &RHS) const { | 
| Chris Lattner | 18884a8 | 2003-10-29 21:41:17 +0000 | [diff] [blame] | 56 | return LHS.second > RHS.second; | 
| Chris Lattner | 7a78d81 | 2003-10-28 21:08:18 +0000 | [diff] [blame] | 57 | } | 
|  | 58 | }; | 
|  | 59 |  | 
| Chris Lattner | 5e71764 | 2003-10-30 23:42:09 +0000 | [diff] [blame] | 60 | namespace { | 
|  | 61 | class ProfileAnnotator : public AssemblyAnnotationWriter { | 
|  | 62 | std::map<const Function  *, unsigned> &FuncFreqs; | 
|  | 63 | std::map<const BasicBlock*, unsigned> &BlockFreqs; | 
| Chris Lattner | 8c2730e | 2004-03-08 20:04:32 +0000 | [diff] [blame] | 64 | std::map<ProfileInfoLoader::Edge, unsigned> &EdgeFreqs; | 
| Chris Lattner | 5e71764 | 2003-10-30 23:42:09 +0000 | [diff] [blame] | 65 | public: | 
|  | 66 | ProfileAnnotator(std::map<const Function  *, unsigned> &FF, | 
| Chris Lattner | 8c2730e | 2004-03-08 20:04:32 +0000 | [diff] [blame] | 67 | std::map<const BasicBlock*, unsigned> &BF, | 
|  | 68 | std::map<ProfileInfoLoader::Edge, unsigned> &EF) | 
|  | 69 | : FuncFreqs(FF), BlockFreqs(BF), EdgeFreqs(EF) {} | 
| Chris Lattner | 5e71764 | 2003-10-30 23:42:09 +0000 | [diff] [blame] | 70 |  | 
|  | 71 | virtual void emitFunctionAnnot(const Function *F, std::ostream &OS) { | 
|  | 72 | OS << ";;; %" << F->getName() << " called " << FuncFreqs[F] | 
|  | 73 | << " times.\n;;;\n"; | 
|  | 74 | } | 
| Chris Lattner | 8c2730e | 2004-03-08 20:04:32 +0000 | [diff] [blame] | 75 | virtual void emitBasicBlockStartAnnot(const BasicBlock *BB, | 
|  | 76 | std::ostream &OS) { | 
| Chris Lattner | 3673730 | 2003-10-30 23:44:28 +0000 | [diff] [blame] | 77 | if (BlockFreqs.empty()) return; | 
| Chris Lattner | 5e71764 | 2003-10-30 23:42:09 +0000 | [diff] [blame] | 78 | if (unsigned Count = BlockFreqs[BB]) | 
| Chris Lattner | 8c2730e | 2004-03-08 20:04:32 +0000 | [diff] [blame] | 79 | OS << "\t;;; Basic block executed " << Count << " times.\n"; | 
| Chris Lattner | 5e71764 | 2003-10-30 23:42:09 +0000 | [diff] [blame] | 80 | else | 
| Chris Lattner | 8c2730e | 2004-03-08 20:04:32 +0000 | [diff] [blame] | 81 | OS << "\t;;; Never executed!\n"; | 
|  | 82 | } | 
|  | 83 |  | 
|  | 84 | virtual void emitBasicBlockEndAnnot(const BasicBlock *BB, std::ostream &OS){ | 
|  | 85 | if (EdgeFreqs.empty()) return; | 
|  | 86 |  | 
|  | 87 | // Figure out how many times each successor executed. | 
|  | 88 | std::vector<std::pair<const BasicBlock*, unsigned> > SuccCounts; | 
|  | 89 | const TerminatorInst *TI = BB->getTerminator(); | 
|  | 90 |  | 
|  | 91 | std::map<ProfileInfoLoader::Edge, unsigned>::iterator I = | 
|  | 92 | EdgeFreqs.lower_bound(std::make_pair(const_cast<BasicBlock*>(BB), 0U)); | 
|  | 93 | for (; I != EdgeFreqs.end() && I->first.first == BB; ++I) | 
|  | 94 | if (I->second) | 
|  | 95 | SuccCounts.push_back(std::make_pair(TI->getSuccessor(I->first.second), | 
|  | 96 | I->second)); | 
|  | 97 | if (!SuccCounts.empty()) { | 
|  | 98 | OS << "\t;;; Out-edge counts:"; | 
|  | 99 | for (unsigned i = 0, e = SuccCounts.size(); i != e; ++i) | 
|  | 100 | OS << " [" << SuccCounts[i].second << " -> " | 
|  | 101 | << SuccCounts[i].first->getName() << "]"; | 
|  | 102 | OS << "\n"; | 
|  | 103 | } | 
| Chris Lattner | 5e71764 | 2003-10-30 23:42:09 +0000 | [diff] [blame] | 104 | } | 
|  | 105 | }; | 
|  | 106 | } | 
|  | 107 |  | 
| Chris Lattner | 7a78d81 | 2003-10-28 21:08:18 +0000 | [diff] [blame] | 108 |  | 
| Chris Lattner | 6f82d07 | 2003-10-28 19:16:35 +0000 | [diff] [blame] | 109 | int main(int argc, char **argv) { | 
|  | 110 | cl::ParseCommandLineOptions(argc, argv, " llvm profile dump decoder\n"); | 
| Reid Spencer | 9de7b33 | 2004-08-29 19:28:55 +0000 | [diff] [blame] | 111 | sys::PrintStackTraceOnErrorSignal(); | 
| Chris Lattner | 6f82d07 | 2003-10-28 19:16:35 +0000 | [diff] [blame] | 112 |  | 
| Chris Lattner | e436779 | 2003-10-28 20:13:07 +0000 | [diff] [blame] | 113 | // Read in the bytecode file... | 
|  | 114 | std::string ErrorMessage; | 
| Chris Lattner | 7a78d81 | 2003-10-28 21:08:18 +0000 | [diff] [blame] | 115 | Module *M = ParseBytecodeFile(BytecodeFile, &ErrorMessage); | 
|  | 116 | if (M == 0) { | 
| Chris Lattner | e436779 | 2003-10-28 20:13:07 +0000 | [diff] [blame] | 117 | std::cerr << argv[0] << ": " << BytecodeFile << ": " << ErrorMessage | 
|  | 118 | << "\n"; | 
|  | 119 | return 1; | 
|  | 120 | } | 
| Chris Lattner | 6f82d07 | 2003-10-28 19:16:35 +0000 | [diff] [blame] | 121 |  | 
| Chris Lattner | e436779 | 2003-10-28 20:13:07 +0000 | [diff] [blame] | 122 | // Read the profiling information | 
| Chris Lattner | 89cf393 | 2004-02-11 05:56:07 +0000 | [diff] [blame] | 123 | ProfileInfoLoader PI(argv[0], ProfileDataFile, *M); | 
| Chris Lattner | 6f82d07 | 2003-10-28 19:16:35 +0000 | [diff] [blame] | 124 |  | 
| Chris Lattner | 5e71764 | 2003-10-30 23:42:09 +0000 | [diff] [blame] | 125 | std::map<const Function  *, unsigned> FuncFreqs; | 
|  | 126 | std::map<const BasicBlock*, unsigned> BlockFreqs; | 
| Chris Lattner | 8c2730e | 2004-03-08 20:04:32 +0000 | [diff] [blame] | 127 | std::map<ProfileInfoLoader::Edge, unsigned> EdgeFreqs; | 
| Chris Lattner | 5e71764 | 2003-10-30 23:42:09 +0000 | [diff] [blame] | 128 |  | 
| Chris Lattner | 7a78d81 | 2003-10-28 21:08:18 +0000 | [diff] [blame] | 129 | // Output a report.  Eventually, there will be multiple reports selectable on | 
|  | 130 | // the command line, for now, just keep things simple. | 
|  | 131 |  | 
|  | 132 | // Emit the most frequent function table... | 
|  | 133 | std::vector<std::pair<Function*, unsigned> > FunctionCounts; | 
|  | 134 | PI.getFunctionCounts(FunctionCounts); | 
| Chris Lattner | 5e71764 | 2003-10-30 23:42:09 +0000 | [diff] [blame] | 135 | FuncFreqs.insert(FunctionCounts.begin(), FunctionCounts.end()); | 
| Chris Lattner | 7a78d81 | 2003-10-28 21:08:18 +0000 | [diff] [blame] | 136 |  | 
|  | 137 | // Sort by the frequency, backwards. | 
|  | 138 | std::sort(FunctionCounts.begin(), FunctionCounts.end(), | 
| Chris Lattner | 18884a8 | 2003-10-29 21:41:17 +0000 | [diff] [blame] | 139 | PairSecondSortReverse<Function*>()); | 
| Chris Lattner | 7a78d81 | 2003-10-28 21:08:18 +0000 | [diff] [blame] | 140 |  | 
| Chris Lattner | 3baed41 | 2003-10-31 00:06:57 +0000 | [diff] [blame] | 141 | unsigned long long TotalExecutions = 0; | 
| Chris Lattner | 7a78d81 | 2003-10-28 21:08:18 +0000 | [diff] [blame] | 142 | for (unsigned i = 0, e = FunctionCounts.size(); i != e; ++i) | 
|  | 143 | TotalExecutions += FunctionCounts[i].second; | 
|  | 144 |  | 
| Chris Lattner | 4963dcf | 2003-10-28 22:30:37 +0000 | [diff] [blame] | 145 | std::cout << "===" << std::string(73, '-') << "===\n" | 
| Chris Lattner | 3688205 | 2003-10-28 22:53:49 +0000 | [diff] [blame] | 146 | << "LLVM profiling output for execution"; | 
|  | 147 | if (PI.getNumExecutions() != 1) std::cout << "s"; | 
|  | 148 | std::cout << ":\n"; | 
| Chris Lattner | 4963dcf | 2003-10-28 22:30:37 +0000 | [diff] [blame] | 149 |  | 
|  | 150 | for (unsigned i = 0, e = PI.getNumExecutions(); i != e; ++i) { | 
|  | 151 | std::cout << "  "; | 
| Chris Lattner | 18884a8 | 2003-10-29 21:41:17 +0000 | [diff] [blame] | 152 | if (e != 1) std::cout << i+1 << ". "; | 
| Chris Lattner | 4963dcf | 2003-10-28 22:30:37 +0000 | [diff] [blame] | 153 | std::cout << PI.getExecution(i) << "\n"; | 
|  | 154 | } | 
|  | 155 |  | 
|  | 156 | std::cout << "\n===" << std::string(73, '-') << "===\n"; | 
|  | 157 | std::cout << "Function execution frequencies:\n\n"; | 
|  | 158 |  | 
| Chris Lattner | 7a78d81 | 2003-10-28 21:08:18 +0000 | [diff] [blame] | 159 | // Print out the function frequencies... | 
|  | 160 | printf(" ##   Frequency\n"); | 
| Chris Lattner | 4963dcf | 2003-10-28 22:30:37 +0000 | [diff] [blame] | 161 | for (unsigned i = 0, e = FunctionCounts.size(); i != e; ++i) { | 
|  | 162 | if (FunctionCounts[i].second == 0) { | 
|  | 163 | printf("\n  NOTE: %d function%s never executed!\n", | 
|  | 164 | e-i, e-i-1 ? "s were" : " was"); | 
|  | 165 | break; | 
|  | 166 | } | 
|  | 167 |  | 
| Chris Lattner | 3baed41 | 2003-10-31 00:06:57 +0000 | [diff] [blame] | 168 | printf("%3d. %5u/%llu %s\n", i+1, FunctionCounts[i].second, TotalExecutions, | 
| Chris Lattner | 7a78d81 | 2003-10-28 21:08:18 +0000 | [diff] [blame] | 169 | FunctionCounts[i].first->getName().c_str()); | 
| Chris Lattner | 4963dcf | 2003-10-28 22:30:37 +0000 | [diff] [blame] | 170 | } | 
| Chris Lattner | 33f1ca7 | 2003-10-28 21:25:23 +0000 | [diff] [blame] | 171 |  | 
| Chris Lattner | 5e71764 | 2003-10-30 23:42:09 +0000 | [diff] [blame] | 172 | std::set<Function*> FunctionsToPrint; | 
| Chris Lattner | 33f1ca7 | 2003-10-28 21:25:23 +0000 | [diff] [blame] | 173 |  | 
|  | 174 | // If we have block count information, print out the LLVM module with | 
|  | 175 | // frequency annotations. | 
|  | 176 | if (PI.hasAccurateBlockCounts()) { | 
|  | 177 | std::vector<std::pair<BasicBlock*, unsigned> > Counts; | 
|  | 178 | PI.getBlockCounts(Counts); | 
| Chris Lattner | 18884a8 | 2003-10-29 21:41:17 +0000 | [diff] [blame] | 179 |  | 
|  | 180 | TotalExecutions = 0; | 
|  | 181 | for (unsigned i = 0, e = Counts.size(); i != e; ++i) | 
|  | 182 | TotalExecutions += Counts[i].second; | 
|  | 183 |  | 
|  | 184 | // Sort by the frequency, backwards. | 
|  | 185 | std::sort(Counts.begin(), Counts.end(), | 
|  | 186 | PairSecondSortReverse<BasicBlock*>()); | 
|  | 187 |  | 
|  | 188 | std::cout << "\n===" << std::string(73, '-') << "===\n"; | 
|  | 189 | std::cout << "Top 20 most frequently executed basic blocks:\n\n"; | 
|  | 190 |  | 
|  | 191 | // Print out the function frequencies... | 
| Chris Lattner | e1ccadf | 2003-10-31 00:13:26 +0000 | [diff] [blame] | 192 | printf(" ##      %%%% \tFrequency\n"); | 
| Chris Lattner | 18884a8 | 2003-10-29 21:41:17 +0000 | [diff] [blame] | 193 | unsigned BlocksToPrint = Counts.size(); | 
|  | 194 | if (BlocksToPrint > 20) BlocksToPrint = 20; | 
| Chris Lattner | 5e71764 | 2003-10-30 23:42:09 +0000 | [diff] [blame] | 195 | for (unsigned i = 0; i != BlocksToPrint; ++i) { | 
| Chris Lattner | 9088de7 | 2003-10-31 00:34:05 +0000 | [diff] [blame] | 196 | if (Counts[i].second == 0) break; | 
| Chris Lattner | 5e71764 | 2003-10-30 23:42:09 +0000 | [diff] [blame] | 197 | Function *F = Counts[i].first->getParent(); | 
| Chris Lattner | e1ccadf | 2003-10-31 00:13:26 +0000 | [diff] [blame] | 198 | printf("%3d. %5.2f%% %5u/%llu\t%s() - %s\n", i+1, | 
|  | 199 | Counts[i].second/(double)TotalExecutions*100, | 
| Chris Lattner | 3baed41 | 2003-10-31 00:06:57 +0000 | [diff] [blame] | 200 | Counts[i].second, TotalExecutions, | 
| Chris Lattner | 5e71764 | 2003-10-30 23:42:09 +0000 | [diff] [blame] | 201 | F->getName().c_str(), Counts[i].first->getName().c_str()); | 
|  | 202 | FunctionsToPrint.insert(F); | 
|  | 203 | } | 
| Chris Lattner | 18884a8 | 2003-10-29 21:41:17 +0000 | [diff] [blame] | 204 |  | 
| Chris Lattner | 5e71764 | 2003-10-30 23:42:09 +0000 | [diff] [blame] | 205 | BlockFreqs.insert(Counts.begin(), Counts.end()); | 
|  | 206 | } | 
|  | 207 |  | 
| Chris Lattner | 8c2730e | 2004-03-08 20:04:32 +0000 | [diff] [blame] | 208 | if (PI.hasAccurateEdgeCounts()) { | 
|  | 209 | std::vector<std::pair<ProfileInfoLoader::Edge, unsigned> > Counts; | 
|  | 210 | PI.getEdgeCounts(Counts); | 
|  | 211 | EdgeFreqs.insert(Counts.begin(), Counts.end()); | 
|  | 212 | } | 
|  | 213 |  | 
| Chris Lattner | cde1cf3 | 2003-11-06 20:29:25 +0000 | [diff] [blame] | 214 | if (PrintAnnotatedLLVM || PrintAllCode) { | 
| Chris Lattner | 5e71764 | 2003-10-30 23:42:09 +0000 | [diff] [blame] | 215 | std::cout << "\n===" << std::string(73, '-') << "===\n"; | 
|  | 216 | std::cout << "Annotated LLVM code for the module:\n\n"; | 
| Chris Lattner | 18884a8 | 2003-10-29 21:41:17 +0000 | [diff] [blame] | 217 |  | 
| Chris Lattner | 8c2730e | 2004-03-08 20:04:32 +0000 | [diff] [blame] | 218 | ProfileAnnotator PA(FuncFreqs, BlockFreqs, EdgeFreqs); | 
| Chris Lattner | 5e71764 | 2003-10-30 23:42:09 +0000 | [diff] [blame] | 219 |  | 
| Chris Lattner | cde1cf3 | 2003-11-06 20:29:25 +0000 | [diff] [blame] | 220 | if (FunctionsToPrint.empty() || PrintAllCode) | 
| Chris Lattner | 3b7f416 | 2003-10-31 00:20:09 +0000 | [diff] [blame] | 221 | M->print(std::cout, &PA); | 
|  | 222 | else | 
|  | 223 | // Print just a subset of the functions... | 
|  | 224 | for (std::set<Function*>::iterator I = FunctionsToPrint.begin(), | 
|  | 225 | E = FunctionsToPrint.end(); I != E; ++I) | 
|  | 226 | (*I)->print(std::cout, &PA); | 
| Chris Lattner | 33f1ca7 | 2003-10-28 21:25:23 +0000 | [diff] [blame] | 227 | } | 
|  | 228 |  | 
| Chris Lattner | 6f82d07 | 2003-10-28 19:16:35 +0000 | [diff] [blame] | 229 | return 0; | 
|  | 230 | } |