llvm-prof.cpp revision 3da94aec4d429b2ba0f65fa040c33650cade196b
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 16#include "llvm/InstrTypes.h" 17#include "llvm/Module.h" 18#include "llvm/Assembly/AsmAnnotationWriter.h" 19#include "llvm/Analysis/ProfileInfoLoader.h" 20#include "llvm/Bytecode/Reader.h" 21#include "llvm/Support/CommandLine.h" 22#include "llvm/System/Signals.h" 23#include <cstdio> 24#include <iostream> 25#include <map> 26#include <set> 27 28using namespace llvm; 29 30namespace { 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")); 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)); 44 cl::opt<bool> 45 PrintAllCode("print-all-code", 46 cl::desc("Print annotated code for the entire program")); 47} 48 49// PairSecondSort - A sorting predicate to sort by the second element of a pair. 50template<class T> 51struct PairSecondSortReverse 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 { 56 return LHS.second > RHS.second; 57 } 58}; 59 60namespace { 61 class ProfileAnnotator : public AssemblyAnnotationWriter { 62 std::map<const Function *, unsigned> &FuncFreqs; 63 std::map<const BasicBlock*, unsigned> &BlockFreqs; 64 std::map<ProfileInfoLoader::Edge, unsigned> &EdgeFreqs; 65 public: 66 ProfileAnnotator(std::map<const Function *, unsigned> &FF, 67 std::map<const BasicBlock*, unsigned> &BF, 68 std::map<ProfileInfoLoader::Edge, unsigned> &EF) 69 : FuncFreqs(FF), BlockFreqs(BF), EdgeFreqs(EF) {} 70 71 virtual void emitFunctionAnnot(const Function *F, std::ostream &OS) { 72 OS << ";;; %" << F->getName() << " called " << FuncFreqs[F] 73 << " times.\n;;;\n"; 74 } 75 virtual void emitBasicBlockStartAnnot(const BasicBlock *BB, 76 std::ostream &OS) { 77 if (BlockFreqs.empty()) return; 78 if (unsigned Count = BlockFreqs[BB]) 79 OS << "\t;;; Basic block executed " << Count << " times.\n"; 80 else 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 } 104 } 105 }; 106} 107 108 109int main(int argc, char **argv) { 110 try { 111 cl::ParseCommandLineOptions(argc, argv, " llvm profile dump decoder\n"); 112 sys::PrintStackTraceOnErrorSignal(); 113 114 // Read in the bytecode file... 115 std::string ErrorMessage; 116 Module *M = ParseBytecodeFile(BytecodeFile, &ErrorMessage); 117 if (M == 0) { 118 std::cerr << argv[0] << ": " << BytecodeFile << ": " << ErrorMessage 119 << "\n"; 120 return 1; 121 } 122 123 // Read the profiling information 124 ProfileInfoLoader PI(argv[0], ProfileDataFile, *M); 125 126 std::map<const Function *, unsigned> FuncFreqs; 127 std::map<const BasicBlock*, unsigned> BlockFreqs; 128 std::map<ProfileInfoLoader::Edge, unsigned> EdgeFreqs; 129 130 // Output a report. Eventually, there will be multiple reports selectable on 131 // the command line, for now, just keep things simple. 132 133 // Emit the most frequent function table... 134 std::vector<std::pair<Function*, unsigned> > FunctionCounts; 135 PI.getFunctionCounts(FunctionCounts); 136 FuncFreqs.insert(FunctionCounts.begin(), FunctionCounts.end()); 137 138 // Sort by the frequency, backwards. 139 std::sort(FunctionCounts.begin(), FunctionCounts.end(), 140 PairSecondSortReverse<Function*>()); 141 142 unsigned long long TotalExecutions = 0; 143 for (unsigned i = 0, e = FunctionCounts.size(); i != e; ++i) 144 TotalExecutions += FunctionCounts[i].second; 145 146 std::cout << "===" << std::string(73, '-') << "===\n" 147 << "LLVM profiling output for execution"; 148 if (PI.getNumExecutions() != 1) std::cout << "s"; 149 std::cout << ":\n"; 150 151 for (unsigned i = 0, e = PI.getNumExecutions(); i != e; ++i) { 152 std::cout << " "; 153 if (e != 1) std::cout << i+1 << ". "; 154 std::cout << PI.getExecution(i) << "\n"; 155 } 156 157 std::cout << "\n===" << std::string(73, '-') << "===\n"; 158 std::cout << "Function execution frequencies:\n\n"; 159 160 // Print out the function frequencies... 161 printf(" ## Frequency\n"); 162 for (unsigned i = 0, e = FunctionCounts.size(); i != e; ++i) { 163 if (FunctionCounts[i].second == 0) { 164 printf("\n NOTE: %d function%s never executed!\n", 165 e-i, e-i-1 ? "s were" : " was"); 166 break; 167 } 168 169 printf("%3d. %5u/%llu %s\n", i+1, FunctionCounts[i].second, TotalExecutions, 170 FunctionCounts[i].first->getName().c_str()); 171 } 172 173 std::set<Function*> FunctionsToPrint; 174 175 // If we have block count information, print out the LLVM module with 176 // frequency annotations. 177 if (PI.hasAccurateBlockCounts()) { 178 std::vector<std::pair<BasicBlock*, unsigned> > Counts; 179 PI.getBlockCounts(Counts); 180 181 TotalExecutions = 0; 182 for (unsigned i = 0, e = Counts.size(); i != e; ++i) 183 TotalExecutions += Counts[i].second; 184 185 // Sort by the frequency, backwards. 186 std::sort(Counts.begin(), Counts.end(), 187 PairSecondSortReverse<BasicBlock*>()); 188 189 std::cout << "\n===" << std::string(73, '-') << "===\n"; 190 std::cout << "Top 20 most frequently executed basic blocks:\n\n"; 191 192 // Print out the function frequencies... 193 printf(" ## %%%% \tFrequency\n"); 194 unsigned BlocksToPrint = Counts.size(); 195 if (BlocksToPrint > 20) BlocksToPrint = 20; 196 for (unsigned i = 0; i != BlocksToPrint; ++i) { 197 if (Counts[i].second == 0) break; 198 Function *F = Counts[i].first->getParent(); 199 printf("%3d. %5.2f%% %5u/%llu\t%s() - %s\n", i+1, 200 Counts[i].second/(double)TotalExecutions*100, 201 Counts[i].second, TotalExecutions, 202 F->getName().c_str(), Counts[i].first->getName().c_str()); 203 FunctionsToPrint.insert(F); 204 } 205 206 BlockFreqs.insert(Counts.begin(), Counts.end()); 207 } 208 209 if (PI.hasAccurateEdgeCounts()) { 210 std::vector<std::pair<ProfileInfoLoader::Edge, unsigned> > Counts; 211 PI.getEdgeCounts(Counts); 212 EdgeFreqs.insert(Counts.begin(), Counts.end()); 213 } 214 215 if (PrintAnnotatedLLVM || PrintAllCode) { 216 std::cout << "\n===" << std::string(73, '-') << "===\n"; 217 std::cout << "Annotated LLVM code for the module:\n\n"; 218 219 ProfileAnnotator PA(FuncFreqs, BlockFreqs, EdgeFreqs); 220 221 if (FunctionsToPrint.empty() || PrintAllCode) 222 M->print(std::cout, &PA); 223 else 224 // Print just a subset of the functions... 225 for (std::set<Function*>::iterator I = FunctionsToPrint.begin(), 226 E = FunctionsToPrint.end(); I != E; ++I) 227 (*I)->print(std::cout, &PA); 228 } 229 230 return 0; 231 } catch (const std::string& msg) { 232 std::cerr << argv[0] << ": " << msg << "\n"; 233 } catch (...) { 234 std::cerr << argv[0] << ": Unexpected unknown exception occurred.\n"; 235 } 236 return 1; 237} 238