PathProfileVerifier.cpp revision 71246fb830eb15cbf6f976de33f623b6bcb27b4b
1//===- PathProfileVerifier.cpp --------------------------------*- C++ -*---===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This verifier derives an edge profile file from current path profile 11// information 12// 13//===----------------------------------------------------------------------===// 14#define DEBUG_TYPE "path-profile-verifier" 15 16#include "llvm/Analysis/Passes.h" 17#include "llvm/Analysis/PathProfileInfo.h" 18#include "llvm/Analysis/ProfileInfoTypes.h" 19#include "llvm/IR/Module.h" 20#include "llvm/Pass.h" 21#include "llvm/Support/CommandLine.h" 22#include "llvm/Support/Debug.h" 23#include "llvm/Support/raw_ostream.h" 24#include <stdio.h> 25 26using namespace llvm; 27 28namespace { 29 class PathProfileVerifier : public ModulePass { 30 private: 31 bool runOnModule(Module &M); 32 33 public: 34 static char ID; // Pass identification, replacement for typeid 35 PathProfileVerifier() : ModulePass(ID) { 36 initializePathProfileVerifierPass(*PassRegistry::getPassRegistry()); 37 } 38 39 40 virtual const char *getPassName() const { 41 return "Path Profiler Verifier"; 42 } 43 44 // The verifier requires the path profile and edge profile. 45 virtual void getAnalysisUsage(AnalysisUsage& AU) const; 46 }; 47} 48 49static cl::opt<std::string> 50EdgeProfileFilename("path-profile-verifier-file", 51 cl::init("edgefrompath.llvmprof.out"), 52 cl::value_desc("filename"), 53 cl::desc("Edge profile file generated by -path-profile-verifier"), 54 cl::Hidden); 55 56char PathProfileVerifier::ID = 0; 57INITIALIZE_PASS(PathProfileVerifier, "path-profile-verifier", 58 "Compare the path profile derived edge profile against the " 59 "edge profile.", true, true) 60 61ModulePass *llvm::createPathProfileVerifierPass() { 62 return new PathProfileVerifier(); 63} 64 65// The verifier requires the path profile and edge profile. 66void PathProfileVerifier::getAnalysisUsage(AnalysisUsage& AU) const { 67 AU.addRequired<PathProfileInfo>(); 68 AU.addPreserved<PathProfileInfo>(); 69} 70 71typedef std::map<unsigned, unsigned> DuplicateToIndexMap; 72typedef std::map<BasicBlock*,DuplicateToIndexMap> BlockToDuplicateMap; 73typedef std::map<BasicBlock*,BlockToDuplicateMap> NestedBlockToIndexMap; 74 75// the verifier iterates through each path to gather the total 76// number of edge frequencies 77bool PathProfileVerifier::runOnModule (Module &M) { 78 PathProfileInfo& pathProfileInfo = getAnalysis<PathProfileInfo>(); 79 80 // setup a data structure to map path edges which index an 81 // array of edge counters 82 NestedBlockToIndexMap arrayMap; 83 unsigned i = 0; 84 for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) { 85 if (F->isDeclaration()) continue; 86 87 arrayMap[(BasicBlock*)0][F->begin()][0] = i++; 88 89 for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) { 90 TerminatorInst *TI = BB->getTerminator(); 91 92 unsigned duplicate = 0; 93 BasicBlock* prev = 0; 94 for (unsigned s = 0, e = TI->getNumSuccessors(); s != e; 95 prev = TI->getSuccessor(s), ++s) { 96 if (prev == TI->getSuccessor(s)) 97 duplicate++; 98 else duplicate = 0; 99 100 arrayMap[BB][TI->getSuccessor(s)][duplicate] = i++; 101 } 102 } 103 } 104 105 std::vector<unsigned> edgeArray(i); 106 107 // iterate through each path and increment the edge counters as needed 108 for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) { 109 if (F->isDeclaration()) continue; 110 111 pathProfileInfo.setCurrentFunction(F); 112 113 DEBUG(dbgs() << "function '" << F->getName() << "' ran " 114 << pathProfileInfo.pathsRun() 115 << "/" << pathProfileInfo.getPotentialPathCount() 116 << " potential paths\n"); 117 118 for( ProfilePathIterator nextPath = pathProfileInfo.pathBegin(), 119 endPath = pathProfileInfo.pathEnd(); 120 nextPath != endPath; nextPath++ ) { 121 ProfilePath* currentPath = nextPath->second; 122 123 ProfilePathEdgeVector* pev = currentPath->getPathEdges(); 124 DEBUG(dbgs () << "path #" << currentPath->getNumber() << ": " 125 << currentPath->getCount() << "\n"); 126 // setup the entry edge (normally path profiling doesn't care about this) 127 if (currentPath->getFirstBlockInPath() == &F->getEntryBlock()) 128 edgeArray[arrayMap[(BasicBlock*)0][currentPath->getFirstBlockInPath()][0]] 129 += currentPath->getCount(); 130 131 for( ProfilePathEdgeIterator nextEdge = pev->begin(), 132 endEdge = pev->end(); nextEdge != endEdge; nextEdge++ ) { 133 if (nextEdge != pev->begin()) 134 DEBUG(dbgs() << " :: "); 135 136 BasicBlock* source = nextEdge->getSource(); 137 BasicBlock* target = nextEdge->getTarget(); 138 unsigned duplicateNumber = nextEdge->getDuplicateNumber(); 139 DEBUG(dbgs() << source->getName() << " --{" << duplicateNumber 140 << "}--> " << target->getName()); 141 142 // Ensure all the referenced edges exist 143 // TODO: make this a separate function 144 if( !arrayMap.count(source) ) { 145 errs() << " error [" << F->getName() << "()]: source '" 146 << source->getName() 147 << "' does not exist in the array map.\n"; 148 } else if( !arrayMap[source].count(target) ) { 149 errs() << " error [" << F->getName() << "()]: target '" 150 << target->getName() 151 << "' does not exist in the array map.\n"; 152 } else if( !arrayMap[source][target].count(duplicateNumber) ) { 153 errs() << " error [" << F->getName() << "()]: edge " 154 << source->getName() << " -> " << target->getName() 155 << " duplicate number " << duplicateNumber 156 << " does not exist in the array map.\n"; 157 } else { 158 edgeArray[arrayMap[source][target][duplicateNumber]] 159 += currentPath->getCount(); 160 } 161 } 162 163 DEBUG(errs() << "\n"); 164 165 delete pev; 166 } 167 } 168 169 std::string errorInfo; 170 std::string filename = EdgeProfileFilename; 171 172 // Open a handle to the file 173 FILE* edgeFile = fopen(filename.c_str(),"wb"); 174 175 if (!edgeFile) { 176 errs() << "error: unable to open file '" << filename << "' for output.\n"; 177 return false; 178 } 179 180 errs() << "Generating edge profile '" << filename << "' ...\n"; 181 182 // write argument info 183 unsigned type = ArgumentInfo; 184 unsigned num = pathProfileInfo.argList.size(); 185 int zeros = 0; 186 187 fwrite(&type,sizeof(unsigned),1,edgeFile); 188 fwrite(&num,sizeof(unsigned),1,edgeFile); 189 fwrite(pathProfileInfo.argList.c_str(),1,num,edgeFile); 190 if (num&3) 191 fwrite(&zeros, 1, 4-(num&3), edgeFile); 192 193 type = EdgeInfo; 194 num = edgeArray.size(); 195 fwrite(&type,sizeof(unsigned),1,edgeFile); 196 fwrite(&num,sizeof(unsigned),1,edgeFile); 197 198 // write each edge to the file 199 for( std::vector<unsigned>::iterator s = edgeArray.begin(), 200 e = edgeArray.end(); s != e; s++) 201 fwrite(&*s, sizeof (unsigned), 1, edgeFile); 202 203 fclose (edgeFile); 204 205 return true; 206} 207