|  | //===- PathProfileInfo.cpp ------------------------------------*- C++ -*---===// | 
|  | // | 
|  | //                     The LLVM Compiler Infrastructure | 
|  | // | 
|  | // This file is distributed under the University of Illinois Open Source | 
|  | // License. See LICENSE.TXT for details. | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  | // | 
|  | // This file defines the interface used by optimizers to load path profiles, | 
|  | // and provides a loader pass which reads a path profile file. | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  | #define DEBUG_TYPE "path-profile-info" | 
|  |  | 
|  | #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/CommandLine.h" | 
|  | #include "llvm/Support/Debug.h" | 
|  | #include "llvm/Support/raw_ostream.h" | 
|  |  | 
|  | #include <cstdio> | 
|  |  | 
|  | using namespace llvm; | 
|  |  | 
|  | // command line option for loading path profiles | 
|  | static cl::opt<std::string> | 
|  | PathProfileInfoFilename("path-profile-loader-file", cl::init("llvmprof.out"), | 
|  | cl::value_desc("filename"), | 
|  | cl::desc("Path profile file loaded by -path-profile-loader"), cl::Hidden); | 
|  |  | 
|  | namespace { | 
|  | class PathProfileLoaderPass : public ModulePass, public PathProfileInfo { | 
|  | public: | 
|  | PathProfileLoaderPass() : ModulePass(ID) { } | 
|  | ~PathProfileLoaderPass(); | 
|  |  | 
|  | // this pass doesn't change anything (only loads information) | 
|  | virtual void getAnalysisUsage(AnalysisUsage &AU) const { | 
|  | AU.setPreservesAll(); | 
|  | } | 
|  |  | 
|  | // the full name of the loader pass | 
|  | virtual const char* getPassName() const { | 
|  | return "Path Profiling Information Loader"; | 
|  | } | 
|  |  | 
|  | // required since this pass implements multiple inheritance | 
|  | virtual void *getAdjustedAnalysisPointer(AnalysisID PI) { | 
|  | if (PI == &PathProfileInfo::ID) | 
|  | return (PathProfileInfo*)this; | 
|  | return this; | 
|  | } | 
|  |  | 
|  | // entry point to run the pass | 
|  | bool runOnModule(Module &M); | 
|  |  | 
|  | // pass identification | 
|  | static char ID; | 
|  |  | 
|  | private: | 
|  | // make a reference table to refer to function by number | 
|  | void buildFunctionRefs(Module &M); | 
|  |  | 
|  | // process argument info of a program from the input file | 
|  | void handleArgumentInfo(); | 
|  |  | 
|  | // process path number information from the input file | 
|  | void handlePathInfo(); | 
|  |  | 
|  | // array of references to the functions in the module | 
|  | std::vector<Function*> _functions; | 
|  |  | 
|  | // path profile file handle | 
|  | FILE* _file; | 
|  |  | 
|  | // path profile file name | 
|  | std::string _filename; | 
|  | }; | 
|  | } | 
|  |  | 
|  | // register PathLoader | 
|  | char PathProfileLoaderPass::ID = 0; | 
|  |  | 
|  | INITIALIZE_ANALYSIS_GROUP(PathProfileInfo, "Path Profile Information", | 
|  | NoPathProfileInfo) | 
|  | INITIALIZE_AG_PASS(PathProfileLoaderPass, PathProfileInfo, | 
|  | "path-profile-loader", | 
|  | "Load path profile information from file", | 
|  | false, true, false) | 
|  |  | 
|  | char &llvm::PathProfileLoaderPassID = PathProfileLoaderPass::ID; | 
|  |  | 
|  | // link PathLoader as a pass, and make it available as an optimisation | 
|  | ModulePass *llvm::createPathProfileLoaderPass() { | 
|  | return new PathProfileLoaderPass; | 
|  | } | 
|  |  | 
|  | // ---------------------------------------------------------------------------- | 
|  | // PathEdge implementation | 
|  | // | 
|  | ProfilePathEdge::ProfilePathEdge (BasicBlock* source, BasicBlock* target, | 
|  | unsigned duplicateNumber) | 
|  | : _source(source), _target(target), _duplicateNumber(duplicateNumber) {} | 
|  |  | 
|  | // ---------------------------------------------------------------------------- | 
|  | // Path implementation | 
|  | // | 
|  |  | 
|  | ProfilePath::ProfilePath (unsigned int number, unsigned int count, | 
|  | double countStdDev,   PathProfileInfo* ppi) | 
|  | : _number(number) , _count(count), _countStdDev(countStdDev), _ppi(ppi) {} | 
|  |  | 
|  | double ProfilePath::getFrequency() const { | 
|  | return 100 * double(_count) / | 
|  | double(_ppi->_functionPathCounts[_ppi->_currentFunction]); | 
|  | } | 
|  |  | 
|  | static BallLarusEdge* getNextEdge (BallLarusNode* node, | 
|  | unsigned int pathNumber) { | 
|  | BallLarusEdge* best = 0; | 
|  |  | 
|  | for( BLEdgeIterator next = node->succBegin(), | 
|  | end = node->succEnd(); next != end; next++ ) { | 
|  | if( (*next)->getType() != BallLarusEdge::BACKEDGE && // no backedges | 
|  | (*next)->getType() != BallLarusEdge::SPLITEDGE && // no split edges | 
|  | (*next)->getWeight() <= pathNumber && // weight must be <= pathNumber | 
|  | (!best || (best->getWeight() < (*next)->getWeight())) ) // best one? | 
|  | best = *next; | 
|  | } | 
|  |  | 
|  | return best; | 
|  | } | 
|  |  | 
|  | ProfilePathEdgeVector* ProfilePath::getPathEdges() const { | 
|  | BallLarusNode* currentNode = _ppi->_currentDag->getRoot (); | 
|  | unsigned int increment = _number; | 
|  | ProfilePathEdgeVector* pev = new ProfilePathEdgeVector; | 
|  |  | 
|  | while (currentNode != _ppi->_currentDag->getExit()) { | 
|  | BallLarusEdge* next = getNextEdge(currentNode, increment); | 
|  |  | 
|  | increment -= next->getWeight(); | 
|  |  | 
|  | if( next->getType() != BallLarusEdge::BACKEDGE_PHONY && | 
|  | next->getType() != BallLarusEdge::SPLITEDGE_PHONY && | 
|  | next->getTarget() != _ppi->_currentDag->getExit() ) | 
|  | pev->push_back(ProfilePathEdge( | 
|  | next->getSource()->getBlock(), | 
|  | next->getTarget()->getBlock(), | 
|  | next->getDuplicateNumber())); | 
|  |  | 
|  | if( next->getType() == BallLarusEdge::BACKEDGE_PHONY && | 
|  | next->getTarget() == _ppi->_currentDag->getExit() ) | 
|  | pev->push_back(ProfilePathEdge( | 
|  | next->getRealEdge()->getSource()->getBlock(), | 
|  | next->getRealEdge()->getTarget()->getBlock(), | 
|  | next->getDuplicateNumber())); | 
|  |  | 
|  | if( next->getType() == BallLarusEdge::SPLITEDGE_PHONY && | 
|  | next->getSource() == _ppi->_currentDag->getRoot() ) | 
|  | pev->push_back(ProfilePathEdge( | 
|  | next->getRealEdge()->getSource()->getBlock(), | 
|  | next->getRealEdge()->getTarget()->getBlock(), | 
|  | next->getDuplicateNumber())); | 
|  |  | 
|  | // set the new node | 
|  | currentNode = next->getTarget(); | 
|  | } | 
|  |  | 
|  | return pev; | 
|  | } | 
|  |  | 
|  | ProfilePathBlockVector* ProfilePath::getPathBlocks() const { | 
|  | BallLarusNode* currentNode = _ppi->_currentDag->getRoot (); | 
|  | unsigned int increment = _number; | 
|  | ProfilePathBlockVector* pbv = new ProfilePathBlockVector; | 
|  |  | 
|  | while (currentNode != _ppi->_currentDag->getExit()) { | 
|  | BallLarusEdge* next = getNextEdge(currentNode, increment); | 
|  | increment -= next->getWeight(); | 
|  |  | 
|  | // add block to the block list if it is a real edge | 
|  | if( next->getType() == BallLarusEdge::NORMAL) | 
|  | pbv->push_back (currentNode->getBlock()); | 
|  | // make the back edge the last edge since we are at the end | 
|  | else if( next->getTarget() == _ppi->_currentDag->getExit() ) { | 
|  | pbv->push_back (currentNode->getBlock()); | 
|  | pbv->push_back (next->getRealEdge()->getTarget()->getBlock()); | 
|  | } | 
|  |  | 
|  | // set the new node | 
|  | currentNode = next->getTarget(); | 
|  | } | 
|  |  | 
|  | return pbv; | 
|  | } | 
|  |  | 
|  | BasicBlock* ProfilePath::getFirstBlockInPath() const { | 
|  | BallLarusNode* root = _ppi->_currentDag->getRoot(); | 
|  | BallLarusEdge* edge = getNextEdge(root, _number); | 
|  |  | 
|  | if( edge && (edge->getType() == BallLarusEdge::BACKEDGE_PHONY || | 
|  | edge->getType() == BallLarusEdge::SPLITEDGE_PHONY) ) | 
|  | return edge->getTarget()->getBlock(); | 
|  |  | 
|  | return root->getBlock(); | 
|  | } | 
|  |  | 
|  | // ---------------------------------------------------------------------------- | 
|  | // PathProfileInfo implementation | 
|  | // | 
|  |  | 
|  | // Pass identification | 
|  | char llvm::PathProfileInfo::ID = 0; | 
|  |  | 
|  | PathProfileInfo::PathProfileInfo () : _currentDag(0) , _currentFunction(0) { | 
|  | } | 
|  |  | 
|  | PathProfileInfo::~PathProfileInfo() { | 
|  | if (_currentDag) | 
|  | delete _currentDag; | 
|  | } | 
|  |  | 
|  | // set the function for which paths are currently begin processed | 
|  | void PathProfileInfo::setCurrentFunction(Function* F) { | 
|  | // Make sure it exists | 
|  | if (!F) return; | 
|  |  | 
|  | if (_currentDag) | 
|  | delete _currentDag; | 
|  |  | 
|  | _currentFunction = F; | 
|  | _currentDag = new BallLarusDag(*F); | 
|  | _currentDag->init(); | 
|  | _currentDag->calculatePathNumbers(); | 
|  | } | 
|  |  | 
|  | // get the function for which paths are currently being processed | 
|  | Function* PathProfileInfo::getCurrentFunction() const { | 
|  | return _currentFunction; | 
|  | } | 
|  |  | 
|  | // get the entry block of the function | 
|  | BasicBlock* PathProfileInfo::getCurrentFunctionEntry() { | 
|  | return _currentDag->getRoot()->getBlock(); | 
|  | } | 
|  |  | 
|  | // return the path based on its number | 
|  | ProfilePath* PathProfileInfo::getPath(unsigned int number) { | 
|  | return _functionPaths[_currentFunction][number]; | 
|  | } | 
|  |  | 
|  | // return the number of paths which a function may potentially execute | 
|  | unsigned int PathProfileInfo::getPotentialPathCount() { | 
|  | return _currentDag ? _currentDag->getNumberOfPaths() : 0; | 
|  | } | 
|  |  | 
|  | // return an iterator for the beginning of a functions executed paths | 
|  | ProfilePathIterator PathProfileInfo::pathBegin() { | 
|  | return _functionPaths[_currentFunction].begin(); | 
|  | } | 
|  |  | 
|  | // return an iterator for the end of a functions executed paths | 
|  | ProfilePathIterator PathProfileInfo::pathEnd() { | 
|  | return _functionPaths[_currentFunction].end(); | 
|  | } | 
|  |  | 
|  | // returns the total number of paths run in the function | 
|  | unsigned int PathProfileInfo::pathsRun() { | 
|  | return _currentFunction ? _functionPaths[_currentFunction].size() : 0; | 
|  | } | 
|  |  | 
|  | // ---------------------------------------------------------------------------- | 
|  | // PathLoader implementation | 
|  | // | 
|  |  | 
|  | // remove all generated paths | 
|  | PathProfileLoaderPass::~PathProfileLoaderPass() { | 
|  | for( FunctionPathIterator funcNext = _functionPaths.begin(), | 
|  | funcEnd = _functionPaths.end(); funcNext != funcEnd; funcNext++) | 
|  | for( ProfilePathIterator pathNext = funcNext->second.begin(), | 
|  | pathEnd = funcNext->second.end(); pathNext != pathEnd; pathNext++) | 
|  | delete pathNext->second; | 
|  | } | 
|  |  | 
|  | // entry point of the pass; this loads and parses a file | 
|  | bool PathProfileLoaderPass::runOnModule(Module &M) { | 
|  | // get the filename and setup the module's function references | 
|  | _filename = PathProfileInfoFilename; | 
|  | buildFunctionRefs (M); | 
|  |  | 
|  | if (!(_file = fopen(_filename.c_str(), "rb"))) { | 
|  | errs () << "error: input '" << _filename << "' file does not exist.\n"; | 
|  | return false; | 
|  | } | 
|  |  | 
|  | ProfilingType profType; | 
|  |  | 
|  | while( fread(&profType, sizeof(ProfilingType), 1, _file) ) { | 
|  | switch (profType) { | 
|  | case ArgumentInfo: | 
|  | handleArgumentInfo (); | 
|  | break; | 
|  | case PathInfo: | 
|  | handlePathInfo (); | 
|  | break; | 
|  | default: | 
|  | errs () << "error: bad path profiling file syntax, " << profType << "\n"; | 
|  | fclose (_file); | 
|  | return false; | 
|  | } | 
|  | } | 
|  |  | 
|  | fclose (_file); | 
|  |  | 
|  | return true; | 
|  | } | 
|  |  | 
|  | // create a reference table for functions defined in the path profile file | 
|  | void PathProfileLoaderPass::buildFunctionRefs (Module &M) { | 
|  | _functions.push_back(0); // make the 0 index a null pointer | 
|  |  | 
|  | for (Module::iterator F = M.begin(), E = M.end(); F != E; F++) { | 
|  | if (F->isDeclaration()) | 
|  | continue; | 
|  | _functions.push_back(F); | 
|  | } | 
|  | } | 
|  |  | 
|  | // handle command like argument infor in the output file | 
|  | void PathProfileLoaderPass::handleArgumentInfo() { | 
|  | // get the argument list's length | 
|  | unsigned savedArgsLength; | 
|  | if( fread(&savedArgsLength, sizeof(unsigned), 1, _file) != 1 ) { | 
|  | errs() << "warning: argument info header/data mismatch\n"; | 
|  | return; | 
|  | } | 
|  |  | 
|  | // allocate a buffer, and get the arguments | 
|  | char* args = new char[savedArgsLength+1]; | 
|  | if( fread(args, 1, savedArgsLength, _file) != savedArgsLength ) | 
|  | errs() << "warning: argument info header/data mismatch\n"; | 
|  |  | 
|  | args[savedArgsLength] = '\0'; | 
|  | argList = std::string(args); | 
|  | delete [] args; // cleanup dynamic string | 
|  |  | 
|  | // byte alignment | 
|  | if (savedArgsLength & 3) | 
|  | fseek(_file, 4-(savedArgsLength&3), SEEK_CUR); | 
|  | } | 
|  |  | 
|  | // Handle path profile information in the output file | 
|  | void PathProfileLoaderPass::handlePathInfo () { | 
|  | // get the number of functions in this profile | 
|  | unsigned functionCount; | 
|  | if( fread(&functionCount, sizeof(functionCount), 1, _file) != 1 ) { | 
|  | errs() << "warning: path info header/data mismatch\n"; | 
|  | return; | 
|  | } | 
|  |  | 
|  | // gather path information for each function | 
|  | for (unsigned i = 0; i < functionCount; i++) { | 
|  | PathProfileHeader pathHeader; | 
|  | if( fread(&pathHeader, sizeof(pathHeader), 1, _file) != 1 ) { | 
|  | errs() << "warning: bad header for path function info\n"; | 
|  | break; | 
|  | } | 
|  |  | 
|  | Function* f = _functions[pathHeader.fnNumber]; | 
|  |  | 
|  | // dynamically allocate a table to store path numbers | 
|  | PathProfileTableEntry* pathTable = | 
|  | new PathProfileTableEntry[pathHeader.numEntries]; | 
|  |  | 
|  | if( fread(pathTable, sizeof(PathProfileTableEntry), | 
|  | pathHeader.numEntries, _file) != pathHeader.numEntries) { | 
|  | delete [] pathTable; | 
|  | errs() << "warning: path function info header/data mismatch\n"; | 
|  | return; | 
|  | } | 
|  |  | 
|  | // Build a new path for the current function | 
|  | unsigned int totalPaths = 0; | 
|  | for (unsigned int j = 0; j < pathHeader.numEntries; j++) { | 
|  | totalPaths += pathTable[j].pathCounter; | 
|  | _functionPaths[f][pathTable[j].pathNumber] | 
|  | = new ProfilePath(pathTable[j].pathNumber, pathTable[j].pathCounter, | 
|  | 0, this); | 
|  | } | 
|  |  | 
|  | _functionPathCounts[f] = totalPaths; | 
|  |  | 
|  | delete [] pathTable; | 
|  | } | 
|  | } | 
|  |  | 
|  | //===----------------------------------------------------------------------===// | 
|  | //  NoProfile PathProfileInfo implementation | 
|  | // | 
|  |  | 
|  | namespace { | 
|  | struct NoPathProfileInfo : public ImmutablePass, public PathProfileInfo { | 
|  | static char ID; // Class identification, replacement for typeinfo | 
|  | NoPathProfileInfo() : ImmutablePass(ID) { | 
|  | initializeNoPathProfileInfoPass(*PassRegistry::getPassRegistry()); | 
|  | } | 
|  |  | 
|  | /// getAdjustedAnalysisPointer - This method is used when a pass implements | 
|  | /// an analysis interface through multiple inheritance.  If needed, it | 
|  | /// should override this to adjust the this pointer as needed for the | 
|  | /// specified pass info. | 
|  | virtual void *getAdjustedAnalysisPointer(AnalysisID PI) { | 
|  | if (PI == &PathProfileInfo::ID) | 
|  | return (PathProfileInfo*)this; | 
|  | return this; | 
|  | } | 
|  |  | 
|  | virtual const char *getPassName() const { | 
|  | return "NoPathProfileInfo"; | 
|  | } | 
|  | }; | 
|  | }  // End of anonymous namespace | 
|  |  | 
|  | char NoPathProfileInfo::ID = 0; | 
|  | // Register this pass... | 
|  | INITIALIZE_AG_PASS(NoPathProfileInfo, PathProfileInfo, "no-path-profile", | 
|  | "No Path Profile Information", false, true, true) | 
|  |  | 
|  | ImmutablePass *llvm::createNoPathProfileInfoPass() { return new NoPathProfileInfo(); } |