diff options
Diffstat (limited to 'contrib/llvm/lib/Analysis/PathProfileVerifier.cpp')
-rw-r--r-- | contrib/llvm/lib/Analysis/PathProfileVerifier.cpp | 207 |
1 files changed, 207 insertions, 0 deletions
diff --git a/contrib/llvm/lib/Analysis/PathProfileVerifier.cpp b/contrib/llvm/lib/Analysis/PathProfileVerifier.cpp new file mode 100644 index 0000000..c549773 --- /dev/null +++ b/contrib/llvm/lib/Analysis/PathProfileVerifier.cpp @@ -0,0 +1,207 @@ +//===- 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 doens'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; +} |