PathProfileVerifier.cpp revision 221345
1218885Sdim//===- PathProfileVerifier.cpp --------------------------------*- C++ -*---===// 2218885Sdim// 3218885Sdim// The LLVM Compiler Infrastructure 4218885Sdim// 5218885Sdim// This file is distributed under the University of Illinois Open Source 6218885Sdim// License. See LICENSE.TXT for details. 7218885Sdim// 8218885Sdim//===----------------------------------------------------------------------===// 9218885Sdim// 10218885Sdim// This verifier derives an edge profile file from current path profile 11218885Sdim// information 12218885Sdim// 13218885Sdim//===----------------------------------------------------------------------===// 14218885Sdim#define DEBUG_TYPE "path-profile-verifier" 15218885Sdim 16218885Sdim#include "llvm/Module.h" 17218885Sdim#include "llvm/Pass.h" 18218885Sdim#include "llvm/Analysis/Passes.h" 19218885Sdim#include "llvm/Analysis/ProfileInfoTypes.h" 20218885Sdim#include "llvm/Analysis/PathProfileInfo.h" 21218885Sdim#include "llvm/Support/Debug.h" 22218885Sdim#include "llvm/Support/CommandLine.h" 23218885Sdim#include "llvm/Support/raw_ostream.h" 24218885Sdim 25218885Sdim#include <stdio.h> 26218885Sdim 27218885Sdimusing namespace llvm; 28218885Sdim 29218885Sdimnamespace { 30218885Sdim class PathProfileVerifier : public ModulePass { 31218885Sdim private: 32218885Sdim bool runOnModule(Module &M); 33218885Sdim 34218885Sdim public: 35218885Sdim static char ID; // Pass identification, replacement for typeid 36218885Sdim PathProfileVerifier() : ModulePass(ID) { 37218885Sdim initializePathProfileVerifierPass(*PassRegistry::getPassRegistry()); 38218885Sdim } 39218885Sdim 40218885Sdim 41218885Sdim virtual const char *getPassName() const { 42218885Sdim return "Path Profiler Verifier"; 43218885Sdim } 44218885Sdim 45218885Sdim // The verifier requires the path profile and edge profile. 46218885Sdim virtual void getAnalysisUsage(AnalysisUsage& AU) const; 47218885Sdim }; 48218885Sdim} 49218885Sdim 50218885Sdimstatic cl::opt<std::string> 51218885SdimEdgeProfileFilename("path-profile-verifier-file", 52218885Sdim cl::init("edgefrompath.llvmprof.out"), 53218885Sdim cl::value_desc("filename"), 54218885Sdim cl::desc("Edge profile file generated by -path-profile-verifier"), 55218885Sdim cl::Hidden); 56218885Sdim 57218885Sdimchar PathProfileVerifier::ID = 0; 58218885SdimINITIALIZE_PASS(PathProfileVerifier, "path-profile-verifier", 59218885Sdim "Compare the path profile derived edge profile against the " 60218885Sdim "edge profile.", true, true) 61218885Sdim 62218885SdimModulePass *llvm::createPathProfileVerifierPass() { 63218885Sdim return new PathProfileVerifier(); 64218885Sdim} 65218885Sdim 66218885Sdim// The verifier requires the path profile and edge profile. 67218885Sdimvoid PathProfileVerifier::getAnalysisUsage(AnalysisUsage& AU) const { 68218885Sdim AU.addRequired<PathProfileInfo>(); 69218885Sdim AU.addPreserved<PathProfileInfo>(); 70218885Sdim} 71218885Sdim 72218885Sdimtypedef std::map<unsigned, unsigned> DuplicateToIndexMap; 73218885Sdimtypedef std::map<BasicBlock*,DuplicateToIndexMap> BlockToDuplicateMap; 74218885Sdimtypedef std::map<BasicBlock*,BlockToDuplicateMap> NestedBlockToIndexMap; 75218885Sdim 76218885Sdim// the verifier iterates through each path to gather the total 77218885Sdim// number of edge frequencies 78218885Sdimbool PathProfileVerifier::runOnModule (Module &M) { 79218885Sdim PathProfileInfo& pathProfileInfo = getAnalysis<PathProfileInfo>(); 80218885Sdim 81218885Sdim // setup a data structure to map path edges which index an 82218885Sdim // array of edge counters 83218885Sdim NestedBlockToIndexMap arrayMap; 84218885Sdim unsigned i = 0; 85218885Sdim for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) { 86218885Sdim if (F->isDeclaration()) continue; 87218885Sdim 88218885Sdim arrayMap[0][F->begin()][0] = i++; 89218885Sdim 90218885Sdim for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) { 91218885Sdim TerminatorInst *TI = BB->getTerminator(); 92218885Sdim 93218885Sdim unsigned duplicate = 0; 94218885Sdim BasicBlock* prev = 0; 95218885Sdim for (unsigned s = 0, e = TI->getNumSuccessors(); s != e; 96218885Sdim prev = TI->getSuccessor(s), ++s) { 97218885Sdim if (prev == TI->getSuccessor(s)) 98218885Sdim duplicate++; 99218885Sdim else duplicate = 0; 100218885Sdim 101218885Sdim arrayMap[BB][TI->getSuccessor(s)][duplicate] = i++; 102218885Sdim } 103218885Sdim } 104218885Sdim } 105218885Sdim 106218885Sdim std::vector<unsigned> edgeArray(i); 107218885Sdim 108218885Sdim // iterate through each path and increment the edge counters as needed 109218885Sdim for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) { 110218885Sdim if (F->isDeclaration()) continue; 111218885Sdim 112218885Sdim pathProfileInfo.setCurrentFunction(F); 113218885Sdim 114218885Sdim DEBUG(dbgs() << "function '" << F->getName() << "' ran " 115218885Sdim << pathProfileInfo.pathsRun() 116218885Sdim << "/" << pathProfileInfo.getPotentialPathCount() 117218885Sdim << " potential paths\n"); 118218885Sdim 119218885Sdim for( ProfilePathIterator nextPath = pathProfileInfo.pathBegin(), 120218885Sdim endPath = pathProfileInfo.pathEnd(); 121218885Sdim nextPath != endPath; nextPath++ ) { 122218885Sdim ProfilePath* currentPath = nextPath->second; 123218885Sdim 124218885Sdim ProfilePathEdgeVector* pev = currentPath->getPathEdges(); 125218885Sdim DEBUG(dbgs () << "path #" << currentPath->getNumber() << ": " 126218885Sdim << currentPath->getCount() << "\n"); 127221345Sdim // setup the entry edge (normally path profiling doesn't care about this) 128218885Sdim if (currentPath->getFirstBlockInPath() == &F->getEntryBlock()) 129218885Sdim edgeArray[arrayMap[0][currentPath->getFirstBlockInPath()][0]] 130218885Sdim += currentPath->getCount(); 131218885Sdim 132218885Sdim for( ProfilePathEdgeIterator nextEdge = pev->begin(), 133218885Sdim endEdge = pev->end(); nextEdge != endEdge; nextEdge++ ) { 134218885Sdim if (nextEdge != pev->begin()) 135218885Sdim DEBUG(dbgs() << " :: "); 136218885Sdim 137218885Sdim BasicBlock* source = nextEdge->getSource(); 138218885Sdim BasicBlock* target = nextEdge->getTarget(); 139218885Sdim unsigned duplicateNumber = nextEdge->getDuplicateNumber(); 140218885Sdim DEBUG(dbgs () << source->getNameStr() << " --{" << duplicateNumber 141218885Sdim << "}--> " << target->getNameStr()); 142218885Sdim 143218885Sdim // Ensure all the referenced edges exist 144218885Sdim // TODO: make this a separate function 145218885Sdim if( !arrayMap.count(source) ) { 146218885Sdim errs() << " error [" << F->getNameStr() << "()]: source '" 147218885Sdim << source->getNameStr() 148218885Sdim << "' does not exist in the array map.\n"; 149218885Sdim } else if( !arrayMap[source].count(target) ) { 150218885Sdim errs() << " error [" << F->getNameStr() << "()]: target '" 151218885Sdim << target->getNameStr() 152218885Sdim << "' does not exist in the array map.\n"; 153218885Sdim } else if( !arrayMap[source][target].count(duplicateNumber) ) { 154218885Sdim errs() << " error [" << F->getNameStr() << "()]: edge " 155218885Sdim << source->getNameStr() << " -> " << target->getNameStr() 156218885Sdim << " duplicate number " << duplicateNumber 157218885Sdim << " does not exist in the array map.\n"; 158218885Sdim } else { 159218885Sdim edgeArray[arrayMap[source][target][duplicateNumber]] 160218885Sdim += currentPath->getCount(); 161218885Sdim } 162218885Sdim } 163218885Sdim 164218885Sdim DEBUG(errs() << "\n"); 165218885Sdim 166218885Sdim delete pev; 167218885Sdim } 168218885Sdim } 169218885Sdim 170218885Sdim std::string errorInfo; 171218885Sdim std::string filename = EdgeProfileFilename; 172218885Sdim 173218885Sdim // Open a handle to the file 174218885Sdim FILE* edgeFile = fopen(filename.c_str(),"wb"); 175218885Sdim 176218885Sdim if (!edgeFile) { 177218885Sdim errs() << "error: unable to open file '" << filename << "' for output.\n"; 178218885Sdim return false; 179218885Sdim } 180218885Sdim 181218885Sdim errs() << "Generating edge profile '" << filename << "' ...\n"; 182218885Sdim 183218885Sdim // write argument info 184218885Sdim unsigned type = ArgumentInfo; 185218885Sdim unsigned num = pathProfileInfo.argList.size(); 186218885Sdim int zeros = 0; 187218885Sdim 188218885Sdim fwrite(&type,sizeof(unsigned),1,edgeFile); 189218885Sdim fwrite(&num,sizeof(unsigned),1,edgeFile); 190218885Sdim fwrite(pathProfileInfo.argList.c_str(),1,num,edgeFile); 191218885Sdim if (num&3) 192218885Sdim fwrite(&zeros, 1, 4-(num&3), edgeFile); 193218885Sdim 194218885Sdim type = EdgeInfo; 195218885Sdim num = edgeArray.size(); 196218885Sdim fwrite(&type,sizeof(unsigned),1,edgeFile); 197218885Sdim fwrite(&num,sizeof(unsigned),1,edgeFile); 198218885Sdim 199218885Sdim // write each edge to the file 200218885Sdim for( std::vector<unsigned>::iterator s = edgeArray.begin(), 201218885Sdim e = edgeArray.end(); s != e; s++) 202218885Sdim fwrite(&*s, sizeof (unsigned), 1, edgeFile); 203218885Sdim 204218885Sdim fclose (edgeFile); 205218885Sdim 206218885Sdim return true; 207218885Sdim} 208