| //===- PathProfileVerifier.cpp --------------------------------*- C++ -*---===// | |
| // | |
| // The LLVM Compiler Infrastructure | |
| // | |
| // This file is distributed under the University of Illinois Open Source | |
| // License. See LICENSE.TXT for details. | |
| // | |
| //===----------------------------------------------------------------------===// | |
| // | |
| // This verifier derives an edge profile file from current path profile | |
| // information | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #define DEBUG_TYPE "path-profile-verifier" | |
| #include "llvm/Module.h" | |
| #include "llvm/Pass.h" | |
| #include "llvm/Analysis/Passes.h" | |
| #include "llvm/Analysis/ProfileInfoTypes.h" | |
| #include "llvm/Analysis/PathProfileInfo.h" | |
| #include "llvm/Support/Debug.h" | |
| #include "llvm/Support/CommandLine.h" | |
| #include "llvm/Support/raw_ostream.h" | |
| #include <stdio.h> | |
| using namespace llvm; | |
| namespace { | |
| class PathProfileVerifier : public ModulePass { | |
| private: | |
| bool runOnModule(Module &M); | |
| public: | |
| static char ID; // Pass identification, replacement for typeid | |
| PathProfileVerifier() : ModulePass(ID) { | |
| initializePathProfileVerifierPass(*PassRegistry::getPassRegistry()); | |
| } | |
| virtual const char *getPassName() const { | |
| return "Path Profiler Verifier"; | |
| } | |
| // The verifier requires the path profile and edge profile. | |
| virtual void getAnalysisUsage(AnalysisUsage& AU) const; | |
| }; | |
| } | |
| static cl::opt<std::string> | |
| EdgeProfileFilename("path-profile-verifier-file", | |
| cl::init("edgefrompath.llvmprof.out"), | |
| cl::value_desc("filename"), | |
| cl::desc("Edge profile file generated by -path-profile-verifier"), | |
| cl::Hidden); | |
| char PathProfileVerifier::ID = 0; | |
| INITIALIZE_PASS(PathProfileVerifier, "path-profile-verifier", | |
| "Compare the path profile derived edge profile against the " | |
| "edge profile.", true, true) | |
| ModulePass *llvm::createPathProfileVerifierPass() { | |
| return new PathProfileVerifier(); | |
| } | |
| // The verifier requires the path profile and edge profile. | |
| void PathProfileVerifier::getAnalysisUsage(AnalysisUsage& AU) const { | |
| AU.addRequired<PathProfileInfo>(); | |
| AU.addPreserved<PathProfileInfo>(); | |
| } | |
| typedef std::map<unsigned, unsigned> DuplicateToIndexMap; | |
| typedef std::map<BasicBlock*,DuplicateToIndexMap> BlockToDuplicateMap; | |
| typedef std::map<BasicBlock*,BlockToDuplicateMap> NestedBlockToIndexMap; | |
| // the verifier iterates through each path to gather the total | |
| // number of edge frequencies | |
| bool PathProfileVerifier::runOnModule (Module &M) { | |
| PathProfileInfo& pathProfileInfo = getAnalysis<PathProfileInfo>(); | |
| // setup a data structure to map path edges which index an | |
| // array of edge counters | |
| NestedBlockToIndexMap arrayMap; | |
| unsigned i = 0; | |
| for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) { | |
| if (F->isDeclaration()) continue; | |
| arrayMap[0][F->begin()][0] = i++; | |
| for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) { | |
| TerminatorInst *TI = BB->getTerminator(); | |
| unsigned duplicate = 0; | |
| BasicBlock* prev = 0; | |
| for (unsigned s = 0, e = TI->getNumSuccessors(); s != e; | |
| prev = TI->getSuccessor(s), ++s) { | |
| if (prev == TI->getSuccessor(s)) | |
| duplicate++; | |
| else duplicate = 0; | |
| arrayMap[BB][TI->getSuccessor(s)][duplicate] = i++; | |
| } | |
| } | |
| } | |
| std::vector<unsigned> edgeArray(i); | |
| // iterate through each path and increment the edge counters as needed | |
| for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) { | |
| if (F->isDeclaration()) continue; | |
| pathProfileInfo.setCurrentFunction(F); | |
| DEBUG(dbgs() << "function '" << F->getName() << "' ran " | |
| << pathProfileInfo.pathsRun() | |
| << "/" << pathProfileInfo.getPotentialPathCount() | |
| << " potential paths\n"); | |
| for( ProfilePathIterator nextPath = pathProfileInfo.pathBegin(), | |
| endPath = pathProfileInfo.pathEnd(); | |
| nextPath != endPath; nextPath++ ) { | |
| ProfilePath* currentPath = nextPath->second; | |
| ProfilePathEdgeVector* pev = currentPath->getPathEdges(); | |
| DEBUG(dbgs () << "path #" << currentPath->getNumber() << ": " | |
| << currentPath->getCount() << "\n"); | |
| // setup the entry edge (normally path profiling doesn't care about this) | |
| if (currentPath->getFirstBlockInPath() == &F->getEntryBlock()) | |
| edgeArray[arrayMap[0][currentPath->getFirstBlockInPath()][0]] | |
| += currentPath->getCount(); | |
| for( ProfilePathEdgeIterator nextEdge = pev->begin(), | |
| endEdge = pev->end(); nextEdge != endEdge; nextEdge++ ) { | |
| if (nextEdge != pev->begin()) | |
| DEBUG(dbgs() << " :: "); | |
| BasicBlock* source = nextEdge->getSource(); | |
| BasicBlock* target = nextEdge->getTarget(); | |
| unsigned duplicateNumber = nextEdge->getDuplicateNumber(); | |
| DEBUG(dbgs () << source->getNameStr() << " --{" << duplicateNumber | |
| << "}--> " << target->getNameStr()); | |
| // Ensure all the referenced edges exist | |
| // TODO: make this a separate function | |
| if( !arrayMap.count(source) ) { | |
| errs() << " error [" << F->getNameStr() << "()]: source '" | |
| << source->getNameStr() | |
| << "' does not exist in the array map.\n"; | |
| } else if( !arrayMap[source].count(target) ) { | |
| errs() << " error [" << F->getNameStr() << "()]: target '" | |
| << target->getNameStr() | |
| << "' does not exist in the array map.\n"; | |
| } else if( !arrayMap[source][target].count(duplicateNumber) ) { | |
| errs() << " error [" << F->getNameStr() << "()]: edge " | |
| << source->getNameStr() << " -> " << target->getNameStr() | |
| << " duplicate number " << duplicateNumber | |
| << " does not exist in the array map.\n"; | |
| } else { | |
| edgeArray[arrayMap[source][target][duplicateNumber]] | |
| += currentPath->getCount(); | |
| } | |
| } | |
| DEBUG(errs() << "\n"); | |
| delete pev; | |
| } | |
| } | |
| std::string errorInfo; | |
| std::string filename = EdgeProfileFilename; | |
| // Open a handle to the file | |
| FILE* edgeFile = fopen(filename.c_str(),"wb"); | |
| if (!edgeFile) { | |
| errs() << "error: unable to open file '" << filename << "' for output.\n"; | |
| return false; | |
| } | |
| errs() << "Generating edge profile '" << filename << "' ...\n"; | |
| // write argument info | |
| unsigned type = ArgumentInfo; | |
| unsigned num = pathProfileInfo.argList.size(); | |
| int zeros = 0; | |
| fwrite(&type,sizeof(unsigned),1,edgeFile); | |
| fwrite(&num,sizeof(unsigned),1,edgeFile); | |
| fwrite(pathProfileInfo.argList.c_str(),1,num,edgeFile); | |
| if (num&3) | |
| fwrite(&zeros, 1, 4-(num&3), edgeFile); | |
| type = EdgeInfo; | |
| num = edgeArray.size(); | |
| fwrite(&type,sizeof(unsigned),1,edgeFile); | |
| fwrite(&num,sizeof(unsigned),1,edgeFile); | |
| // write each edge to the file | |
| for( std::vector<unsigned>::iterator s = edgeArray.begin(), | |
| e = edgeArray.end(); s != e; s++) | |
| fwrite(&*s, sizeof (unsigned), 1, edgeFile); | |
| fclose (edgeFile); | |
| return true; | |
| } |