//===- 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; }