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