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