| 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 | e436779 | 2003-10-28 20:13:07 +0000 | [diff] [blame] | 16 | #include "ProfileInfo.h" | 
| Chris Lattner | 7a78d81 | 2003-10-28 21:08:18 +0000 | [diff] [blame] | 17 | #include "llvm/Function.h" | 
| Chris Lattner | 6f82d07 | 2003-10-28 19:16:35 +0000 | [diff] [blame] | 18 | #include "llvm/Bytecode/Reader.h" | 
 | 19 | #include "Support/CommandLine.h" | 
| Chris Lattner | e436779 | 2003-10-28 20:13:07 +0000 | [diff] [blame] | 20 | #include <iostream> | 
| Chris Lattner | 7a78d81 | 2003-10-28 21:08:18 +0000 | [diff] [blame] | 21 | #include <cstdio> | 
| Chris Lattner | 33f1ca7 | 2003-10-28 21:25:23 +0000 | [diff] [blame] | 22 | #include <map> | 
| Chris Lattner | 6f82d07 | 2003-10-28 19:16:35 +0000 | [diff] [blame] | 23 |  | 
 | 24 | namespace { | 
 | 25 |   cl::opt<std::string>  | 
 | 26 |   BytecodeFile(cl::Positional, cl::desc("<program bytecode file>"), | 
 | 27 |                cl::Required); | 
 | 28 |  | 
 | 29 |   cl::opt<std::string>  | 
 | 30 |   ProfileDataFile(cl::Positional, cl::desc("<llvmprof.out file>"), | 
 | 31 |                   cl::Optional, cl::init("llvmprof.out")); | 
 | 32 | } | 
 | 33 |  | 
| Chris Lattner | 7a78d81 | 2003-10-28 21:08:18 +0000 | [diff] [blame] | 34 | // PairSecondSort - A sorting predicate to sort by the second element of a pair. | 
 | 35 | template<class T> | 
| Chris Lattner | 18884a8 | 2003-10-29 21:41:17 +0000 | [diff] [blame^] | 36 | struct PairSecondSortReverse | 
| Chris Lattner | 7a78d81 | 2003-10-28 21:08:18 +0000 | [diff] [blame] | 37 |   : public std::binary_function<std::pair<T, unsigned>, | 
 | 38 |                                 std::pair<T, unsigned>, bool> { | 
 | 39 |   bool operator()(const std::pair<T, unsigned> &LHS, | 
 | 40 |                   const std::pair<T, unsigned> &RHS) const { | 
| Chris Lattner | 18884a8 | 2003-10-29 21:41:17 +0000 | [diff] [blame^] | 41 |     return LHS.second > RHS.second; | 
| Chris Lattner | 7a78d81 | 2003-10-28 21:08:18 +0000 | [diff] [blame] | 42 |   } | 
 | 43 | }; | 
 | 44 |  | 
 | 45 |  | 
| Chris Lattner | 6f82d07 | 2003-10-28 19:16:35 +0000 | [diff] [blame] | 46 | int main(int argc, char **argv) { | 
 | 47 |   cl::ParseCommandLineOptions(argc, argv, " llvm profile dump decoder\n"); | 
| Chris Lattner | 6f82d07 | 2003-10-28 19:16:35 +0000 | [diff] [blame] | 48 |  | 
| Chris Lattner | e436779 | 2003-10-28 20:13:07 +0000 | [diff] [blame] | 49 |   // Read in the bytecode file... | 
 | 50 |   std::string ErrorMessage; | 
| Chris Lattner | 7a78d81 | 2003-10-28 21:08:18 +0000 | [diff] [blame] | 51 |   Module *M = ParseBytecodeFile(BytecodeFile, &ErrorMessage); | 
 | 52 |   if (M == 0) { | 
| Chris Lattner | e436779 | 2003-10-28 20:13:07 +0000 | [diff] [blame] | 53 |     std::cerr << argv[0] << ": " << BytecodeFile << ": " << ErrorMessage | 
 | 54 |               << "\n"; | 
 | 55 |     return 1; | 
 | 56 |   } | 
| Chris Lattner | 6f82d07 | 2003-10-28 19:16:35 +0000 | [diff] [blame] | 57 |  | 
| Chris Lattner | e436779 | 2003-10-28 20:13:07 +0000 | [diff] [blame] | 58 |   // Read the profiling information | 
| Chris Lattner | 7a78d81 | 2003-10-28 21:08:18 +0000 | [diff] [blame] | 59 |   ProfileInfo PI(argv[0], ProfileDataFile, *M); | 
| Chris Lattner | 6f82d07 | 2003-10-28 19:16:35 +0000 | [diff] [blame] | 60 |  | 
| Chris Lattner | 7a78d81 | 2003-10-28 21:08:18 +0000 | [diff] [blame] | 61 |   // Output a report.  Eventually, there will be multiple reports selectable on | 
 | 62 |   // the command line, for now, just keep things simple. | 
 | 63 |  | 
 | 64 |   // Emit the most frequent function table... | 
 | 65 |   std::vector<std::pair<Function*, unsigned> > FunctionCounts; | 
 | 66 |   PI.getFunctionCounts(FunctionCounts); | 
 | 67 |  | 
 | 68 |   // Sort by the frequency, backwards. | 
 | 69 |   std::sort(FunctionCounts.begin(), FunctionCounts.end(), | 
| Chris Lattner | 18884a8 | 2003-10-29 21:41:17 +0000 | [diff] [blame^] | 70 |             PairSecondSortReverse<Function*>()); | 
| Chris Lattner | 7a78d81 | 2003-10-28 21:08:18 +0000 | [diff] [blame] | 71 |  | 
 | 72 |   unsigned TotalExecutions = 0; | 
 | 73 |   for (unsigned i = 0, e = FunctionCounts.size(); i != e; ++i) | 
 | 74 |     TotalExecutions += FunctionCounts[i].second; | 
 | 75 |    | 
| Chris Lattner | 4963dcf | 2003-10-28 22:30:37 +0000 | [diff] [blame] | 76 |   std::cout << "===" << std::string(73, '-') << "===\n" | 
| Chris Lattner | 3688205 | 2003-10-28 22:53:49 +0000 | [diff] [blame] | 77 |             << "LLVM profiling output for execution"; | 
 | 78 |   if (PI.getNumExecutions() != 1) std::cout << "s"; | 
 | 79 |   std::cout << ":\n"; | 
| Chris Lattner | 4963dcf | 2003-10-28 22:30:37 +0000 | [diff] [blame] | 80 |    | 
 | 81 |   for (unsigned i = 0, e = PI.getNumExecutions(); i != e; ++i) { | 
 | 82 |     std::cout << "  "; | 
| Chris Lattner | 18884a8 | 2003-10-29 21:41:17 +0000 | [diff] [blame^] | 83 |     if (e != 1) std::cout << i+1 << ". "; | 
| Chris Lattner | 4963dcf | 2003-10-28 22:30:37 +0000 | [diff] [blame] | 84 |     std::cout << PI.getExecution(i) << "\n"; | 
 | 85 |   } | 
 | 86 |    | 
 | 87 |   std::cout << "\n===" << std::string(73, '-') << "===\n"; | 
 | 88 |   std::cout << "Function execution frequencies:\n\n"; | 
 | 89 |  | 
| Chris Lattner | 7a78d81 | 2003-10-28 21:08:18 +0000 | [diff] [blame] | 90 |   // Print out the function frequencies... | 
 | 91 |   printf(" ##   Frequency\n"); | 
| Chris Lattner | 4963dcf | 2003-10-28 22:30:37 +0000 | [diff] [blame] | 92 |   for (unsigned i = 0, e = FunctionCounts.size(); i != e; ++i) { | 
 | 93 |     if (FunctionCounts[i].second == 0) { | 
 | 94 |       printf("\n  NOTE: %d function%s never executed!\n", | 
 | 95 |              e-i, e-i-1 ? "s were" : " was"); | 
 | 96 |       break; | 
 | 97 |     } | 
 | 98 |  | 
| Chris Lattner | 18884a8 | 2003-10-29 21:41:17 +0000 | [diff] [blame^] | 99 |     printf("%3d. %5d/%d %s\n", i+1, FunctionCounts[i].second, TotalExecutions, | 
| Chris Lattner | 7a78d81 | 2003-10-28 21:08:18 +0000 | [diff] [blame] | 100 |            FunctionCounts[i].first->getName().c_str()); | 
| Chris Lattner | 4963dcf | 2003-10-28 22:30:37 +0000 | [diff] [blame] | 101 |   } | 
| Chris Lattner | 33f1ca7 | 2003-10-28 21:25:23 +0000 | [diff] [blame] | 102 |  | 
 | 103 |  | 
 | 104 |   // If we have block count information, print out the LLVM module with | 
 | 105 |   // frequency annotations. | 
 | 106 |   if (PI.hasAccurateBlockCounts()) { | 
 | 107 |     std::vector<std::pair<BasicBlock*, unsigned> > Counts; | 
 | 108 |     PI.getBlockCounts(Counts); | 
| Chris Lattner | 18884a8 | 2003-10-29 21:41:17 +0000 | [diff] [blame^] | 109 |  | 
 | 110 |     TotalExecutions = 0; | 
 | 111 |     for (unsigned i = 0, e = Counts.size(); i != e; ++i) | 
 | 112 |       TotalExecutions += Counts[i].second; | 
 | 113 |  | 
 | 114 |     // Sort by the frequency, backwards. | 
 | 115 |     std::sort(Counts.begin(), Counts.end(), | 
 | 116 |               PairSecondSortReverse<BasicBlock*>()); | 
 | 117 |      | 
 | 118 |     std::cout << "\n===" << std::string(73, '-') << "===\n"; | 
 | 119 |     std::cout << "Top 20 most frequently executed basic blocks:\n\n"; | 
 | 120 |  | 
 | 121 |     // Print out the function frequencies... | 
 | 122 |     printf(" ##   Frequency\n"); | 
 | 123 |     unsigned BlocksToPrint = Counts.size(); | 
 | 124 |     if (BlocksToPrint > 20) BlocksToPrint = 20; | 
 | 125 |     for (unsigned i = 0; i != BlocksToPrint; ++i) | 
 | 126 |       printf("%3d. %5d/%d %s - %s\n", i+1, Counts[i].second, TotalExecutions, | 
 | 127 |              Counts[i].first->getParent()->getName().c_str(), | 
 | 128 |              Counts[i].first->getName().c_str()); | 
 | 129 |  | 
| Chris Lattner | 33f1ca7 | 2003-10-28 21:25:23 +0000 | [diff] [blame] | 130 |     std::map<BasicBlock*, unsigned> BlockFreqs(Counts.begin(), Counts.end()); | 
| Chris Lattner | 18884a8 | 2003-10-29 21:41:17 +0000 | [diff] [blame^] | 131 |      | 
| Chris Lattner | 33f1ca7 | 2003-10-28 21:25:23 +0000 | [diff] [blame] | 132 |   } | 
 | 133 |  | 
| Chris Lattner | 6f82d07 | 2003-10-28 19:16:35 +0000 | [diff] [blame] | 134 |   return 0; | 
 | 135 | } |