| //===- PathNumbering.cpp --------------------------------------*- C++ -*---===// | |
| // | |
| // The LLVM Compiler Infrastructure | |
| // | |
| // This file is distributed under the University of Illinois Open Source | |
| // License. See LICENSE.TXT for details. | |
| // | |
| //===----------------------------------------------------------------------===// | |
| // | |
| // Ball-Larus path numbers uniquely identify paths through a directed acyclic | |
| // graph (DAG) [Ball96]. For a CFG backedges are removed and replaced by phony | |
| // edges to obtain a DAG, and thus the unique path numbers [Ball96]. | |
| // | |
| // The purpose of this analysis is to enumerate the edges in a CFG in order | |
| // to obtain paths from path numbers in a convenient manner. As described in | |
| // [Ball96] edges can be enumerated such that given a path number by following | |
| // the CFG and updating the path number, the path is obtained. | |
| // | |
| // [Ball96] | |
| // T. Ball and J. R. Larus. "Efficient Path Profiling." | |
| // International Symposium on Microarchitecture, pages 46-57, 1996. | |
| // http://portal.acm.org/citation.cfm?id=243857 | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #define DEBUG_TYPE "ball-larus-numbering" | |
| #include "llvm/Analysis/PathNumbering.h" | |
| #include "llvm/Constants.h" | |
| #include "llvm/DerivedTypes.h" | |
| #include "llvm/InstrTypes.h" | |
| #include "llvm/Instructions.h" | |
| #include "llvm/Module.h" | |
| #include "llvm/Pass.h" | |
| #include "llvm/Support/CFG.h" | |
| #include "llvm/Support/CommandLine.h" | |
| #include "llvm/Support/Compiler.h" | |
| #include "llvm/Support/Debug.h" | |
| #include "llvm/Support/TypeBuilder.h" | |
| #include "llvm/Support/raw_ostream.h" | |
| #include <queue> | |
| #include <stack> | |
| #include <string> | |
| #include <utility> | |
| #include <sstream> | |
| using namespace llvm; | |
| // Are we enabling early termination | |
| static cl::opt<bool> ProcessEarlyTermination( | |
| "path-profile-early-termination", cl::Hidden, | |
| cl::desc("In path profiling, insert extra instrumentation to account for " | |
| "unexpected function termination.")); | |
| // Returns the basic block for the BallLarusNode | |
| BasicBlock* BallLarusNode::getBlock() { | |
| return(_basicBlock); | |
| } | |
| // Returns the number of paths to the exit starting at the node. | |
| unsigned BallLarusNode::getNumberPaths() { | |
| return(_numberPaths); | |
| } | |
| // Sets the number of paths to the exit starting at the node. | |
| void BallLarusNode::setNumberPaths(unsigned numberPaths) { | |
| _numberPaths = numberPaths; | |
| } | |
| // Gets the NodeColor used in graph algorithms. | |
| BallLarusNode::NodeColor BallLarusNode::getColor() { | |
| return(_color); | |
| } | |
| // Sets the NodeColor used in graph algorithms. | |
| void BallLarusNode::setColor(BallLarusNode::NodeColor color) { | |
| _color = color; | |
| } | |
| // Returns an iterator over predecessor edges. Includes phony and | |
| // backedges. | |
| BLEdgeIterator BallLarusNode::predBegin() { | |
| return(_predEdges.begin()); | |
| } | |
| // Returns the end sentinel for the predecessor iterator. | |
| BLEdgeIterator BallLarusNode::predEnd() { | |
| return(_predEdges.end()); | |
| } | |
| // Returns the number of predecessor edges. Includes phony and | |
| // backedges. | |
| unsigned BallLarusNode::getNumberPredEdges() { | |
| return(_predEdges.size()); | |
| } | |
| // Returns an iterator over successor edges. Includes phony and | |
| // backedges. | |
| BLEdgeIterator BallLarusNode::succBegin() { | |
| return(_succEdges.begin()); | |
| } | |
| // Returns the end sentinel for the successor iterator. | |
| BLEdgeIterator BallLarusNode::succEnd() { | |
| return(_succEdges.end()); | |
| } | |
| // Returns the number of successor edges. Includes phony and | |
| // backedges. | |
| unsigned BallLarusNode::getNumberSuccEdges() { | |
| return(_succEdges.size()); | |
| } | |
| // Add an edge to the predecessor list. | |
| void BallLarusNode::addPredEdge(BallLarusEdge* edge) { | |
| _predEdges.push_back(edge); | |
| } | |
| // Remove an edge from the predecessor list. | |
| void BallLarusNode::removePredEdge(BallLarusEdge* edge) { | |
| removeEdge(_predEdges, edge); | |
| } | |
| // Add an edge to the successor list. | |
| void BallLarusNode::addSuccEdge(BallLarusEdge* edge) { | |
| _succEdges.push_back(edge); | |
| } | |
| // Remove an edge from the successor list. | |
| void BallLarusNode::removeSuccEdge(BallLarusEdge* edge) { | |
| removeEdge(_succEdges, edge); | |
| } | |
| // Returns the name of the BasicBlock being represented. If BasicBlock | |
| // is null then returns "<null>". If BasicBlock has no name, then | |
| // "<unnamed>" is returned. Intended for use with debug output. | |
| std::string BallLarusNode::getName() { | |
| std::stringstream name; | |
| if(getBlock() != NULL) { | |
| if(getBlock()->hasName()) { | |
| std::string tempName(getBlock()->getName()); | |
| name << tempName.c_str() << " (" << _uid << ")"; | |
| } else | |
| name << "<unnamed> (" << _uid << ")"; | |
| } else | |
| name << "<null> (" << _uid << ")"; | |
| return name.str(); | |
| } | |
| // Removes an edge from an edgeVector. Used by removePredEdge and | |
| // removeSuccEdge. | |
| void BallLarusNode::removeEdge(BLEdgeVector& v, BallLarusEdge* e) { | |
| // TODO: Avoid linear scan by using a set instead | |
| for(BLEdgeIterator i = v.begin(), | |
| end = v.end(); | |
| i != end; | |
| ++i) { | |
| if((*i) == e) { | |
| v.erase(i); | |
| break; | |
| } | |
| } | |
| } | |
| // Returns the source node of this edge. | |
| BallLarusNode* BallLarusEdge::getSource() const { | |
| return(_source); | |
| } | |
| // Returns the target node of this edge. | |
| BallLarusNode* BallLarusEdge::getTarget() const { | |
| return(_target); | |
| } | |
| // Sets the type of the edge. | |
| BallLarusEdge::EdgeType BallLarusEdge::getType() const { | |
| return _edgeType; | |
| } | |
| // Gets the type of the edge. | |
| void BallLarusEdge::setType(EdgeType type) { | |
| _edgeType = type; | |
| } | |
| // Returns the weight of this edge. Used to decode path numbers to sequences | |
| // of basic blocks. | |
| unsigned BallLarusEdge::getWeight() { | |
| return(_weight); | |
| } | |
| // Sets the weight of the edge. Used during path numbering. | |
| void BallLarusEdge::setWeight(unsigned weight) { | |
| _weight = weight; | |
| } | |
| // Gets the phony edge originating at the root. | |
| BallLarusEdge* BallLarusEdge::getPhonyRoot() { | |
| return _phonyRoot; | |
| } | |
| // Sets the phony edge originating at the root. | |
| void BallLarusEdge::setPhonyRoot(BallLarusEdge* phonyRoot) { | |
| _phonyRoot = phonyRoot; | |
| } | |
| // Gets the phony edge terminating at the exit. | |
| BallLarusEdge* BallLarusEdge::getPhonyExit() { | |
| return _phonyExit; | |
| } | |
| // Sets the phony edge terminating at the exit. | |
| void BallLarusEdge::setPhonyExit(BallLarusEdge* phonyExit) { | |
| _phonyExit = phonyExit; | |
| } | |
| // Gets the associated real edge if this is a phony edge. | |
| BallLarusEdge* BallLarusEdge::getRealEdge() { | |
| return _realEdge; | |
| } | |
| // Sets the associated real edge if this is a phony edge. | |
| void BallLarusEdge::setRealEdge(BallLarusEdge* realEdge) { | |
| _realEdge = realEdge; | |
| } | |
| // Returns the duplicate number of the edge. | |
| unsigned BallLarusEdge::getDuplicateNumber() { | |
| return(_duplicateNumber); | |
| } | |
| // Initialization that requires virtual functions which are not fully | |
| // functional in the constructor. | |
| void BallLarusDag::init() { | |
| BLBlockNodeMap inDag; | |
| std::stack<BallLarusNode*> dfsStack; | |
| _root = addNode(&(_function.getEntryBlock())); | |
| _exit = addNode(NULL); | |
| // start search from root | |
| dfsStack.push(getRoot()); | |
| // dfs to add each bb into the dag | |
| while(dfsStack.size()) | |
| buildNode(inDag, dfsStack); | |
| // put in the final edge | |
| addEdge(getExit(),getRoot(),0); | |
| } | |
| // Frees all memory associated with the DAG. | |
| BallLarusDag::~BallLarusDag() { | |
| for(BLEdgeIterator edge = _edges.begin(), end = _edges.end(); edge != end; | |
| ++edge) | |
| delete (*edge); | |
| for(BLNodeIterator node = _nodes.begin(), end = _nodes.end(); node != end; | |
| ++node) | |
| delete (*node); | |
| } | |
| // Calculate the path numbers by assigning edge increments as prescribed | |
| // in Ball-Larus path profiling. | |
| void BallLarusDag::calculatePathNumbers() { | |
| BallLarusNode* node; | |
| std::queue<BallLarusNode*> bfsQueue; | |
| bfsQueue.push(getExit()); | |
| while(bfsQueue.size() > 0) { | |
| node = bfsQueue.front(); | |
| DEBUG(dbgs() << "calculatePathNumbers on " << node->getName() << "\n"); | |
| bfsQueue.pop(); | |
| unsigned prevPathNumber = node->getNumberPaths(); | |
| calculatePathNumbersFrom(node); | |
| // Check for DAG splitting | |
| if( node->getNumberPaths() > 100000000 && node != getRoot() ) { | |
| // Add new phony edge from the split-node to the DAG's exit | |
| BallLarusEdge* exitEdge = addEdge(node, getExit(), 0); | |
| exitEdge->setType(BallLarusEdge::SPLITEDGE_PHONY); | |
| // Counters to handle the possibility of a multi-graph | |
| BasicBlock* oldTarget = 0; | |
| unsigned duplicateNumber = 0; | |
| // Iterate through each successor edge, adding phony edges | |
| for( BLEdgeIterator succ = node->succBegin(), end = node->succEnd(); | |
| succ != end; oldTarget = (*succ)->getTarget()->getBlock(), succ++ ) { | |
| if( (*succ)->getType() == BallLarusEdge::NORMAL ) { | |
| // is this edge a duplicate? | |
| if( oldTarget != (*succ)->getTarget()->getBlock() ) | |
| duplicateNumber = 0; | |
| // create the new phony edge: root -> succ | |
| BallLarusEdge* rootEdge = | |
| addEdge(getRoot(), (*succ)->getTarget(), duplicateNumber++); | |
| rootEdge->setType(BallLarusEdge::SPLITEDGE_PHONY); | |
| rootEdge->setRealEdge(*succ); | |
| // split on this edge and reference it's exit/root phony edges | |
| (*succ)->setType(BallLarusEdge::SPLITEDGE); | |
| (*succ)->setPhonyRoot(rootEdge); | |
| (*succ)->setPhonyExit(exitEdge); | |
| (*succ)->setWeight(0); | |
| } | |
| } | |
| calculatePathNumbersFrom(node); | |
| } | |
| DEBUG(dbgs() << "prev, new number paths " << prevPathNumber << ", " | |
| << node->getNumberPaths() << ".\n"); | |
| if(prevPathNumber == 0 && node->getNumberPaths() != 0) { | |
| DEBUG(dbgs() << "node ready : " << node->getName() << "\n"); | |
| for(BLEdgeIterator pred = node->predBegin(), end = node->predEnd(); | |
| pred != end; pred++) { | |
| if( (*pred)->getType() == BallLarusEdge::BACKEDGE || | |
| (*pred)->getType() == BallLarusEdge::SPLITEDGE ) | |
| continue; | |
| BallLarusNode* nextNode = (*pred)->getSource(); | |
| // not yet visited? | |
| if(nextNode->getNumberPaths() == 0) | |
| bfsQueue.push(nextNode); | |
| } | |
| } | |
| } | |
| DEBUG(dbgs() << "\tNumber of paths: " << getRoot()->getNumberPaths() << "\n"); | |
| } | |
| // Returns the number of paths for the Dag. | |
| unsigned BallLarusDag::getNumberOfPaths() { | |
| return(getRoot()->getNumberPaths()); | |
| } | |
| // Returns the root (i.e. entry) node for the DAG. | |
| BallLarusNode* BallLarusDag::getRoot() { | |
| return _root; | |
| } | |
| // Returns the exit node for the DAG. | |
| BallLarusNode* BallLarusDag::getExit() { | |
| return _exit; | |
| } | |
| // Returns the function for the DAG. | |
| Function& BallLarusDag::getFunction() { | |
| return(_function); | |
| } | |
| // Clears the node colors. | |
| void BallLarusDag::clearColors(BallLarusNode::NodeColor color) { | |
| for (BLNodeIterator nodeIt = _nodes.begin(); nodeIt != _nodes.end(); nodeIt++) | |
| (*nodeIt)->setColor(color); | |
| } | |
| // Processes one node and its imediate edges for building the DAG. | |
| void BallLarusDag::buildNode(BLBlockNodeMap& inDag, BLNodeStack& dfsStack) { | |
| BallLarusNode* currentNode = dfsStack.top(); | |
| BasicBlock* currentBlock = currentNode->getBlock(); | |
| if(currentNode->getColor() != BallLarusNode::WHITE) { | |
| // we have already visited this node | |
| dfsStack.pop(); | |
| currentNode->setColor(BallLarusNode::BLACK); | |
| } else { | |
| // are there any external procedure calls? | |
| if( ProcessEarlyTermination ) { | |
| for( BasicBlock::iterator bbCurrent = currentNode->getBlock()->begin(), | |
| bbEnd = currentNode->getBlock()->end(); bbCurrent != bbEnd; | |
| bbCurrent++ ) { | |
| Instruction& instr = *bbCurrent; | |
| if( instr.getOpcode() == Instruction::Call ) { | |
| BallLarusEdge* callEdge = addEdge(currentNode, getExit(), 0); | |
| callEdge->setType(BallLarusEdge::CALLEDGE_PHONY); | |
| break; | |
| } | |
| } | |
| } | |
| TerminatorInst* terminator = currentNode->getBlock()->getTerminator(); | |
| if(isa<ReturnInst>(terminator) || isa<UnreachableInst>(terminator) | |
| || isa<ResumeInst>(terminator) || isa<UnwindInst>(terminator)) | |
| addEdge(currentNode, getExit(),0); | |
| currentNode->setColor(BallLarusNode::GRAY); | |
| inDag[currentBlock] = currentNode; | |
| BasicBlock* oldSuccessor = 0; | |
| unsigned duplicateNumber = 0; | |
| // iterate through this node's successors | |
| for(succ_iterator successor = succ_begin(currentBlock), | |
| succEnd = succ_end(currentBlock); successor != succEnd; | |
| oldSuccessor = *successor, ++successor ) { | |
| BasicBlock* succBB = *successor; | |
| // is this edge a duplicate? | |
| if (oldSuccessor == succBB) | |
| duplicateNumber++; | |
| else | |
| duplicateNumber = 0; | |
| buildEdge(inDag, dfsStack, currentNode, succBB, duplicateNumber); | |
| } | |
| } | |
| } | |
| // Process an edge in the CFG for DAG building. | |
| void BallLarusDag::buildEdge(BLBlockNodeMap& inDag, std::stack<BallLarusNode*>& | |
| dfsStack, BallLarusNode* currentNode, | |
| BasicBlock* succBB, unsigned duplicateCount) { | |
| BallLarusNode* succNode = inDag[succBB]; | |
| if(succNode && succNode->getColor() == BallLarusNode::BLACK) { | |
| // visited node and forward edge | |
| addEdge(currentNode, succNode, duplicateCount); | |
| } else if(succNode && succNode->getColor() == BallLarusNode::GRAY) { | |
| // visited node and back edge | |
| DEBUG(dbgs() << "Backedge detected.\n"); | |
| addBackedge(currentNode, succNode, duplicateCount); | |
| } else { | |
| BallLarusNode* childNode; | |
| // not visited node and forward edge | |
| if(succNode) // an unvisited node that is child of a gray node | |
| childNode = succNode; | |
| else { // an unvisited node that is a child of a an unvisted node | |
| childNode = addNode(succBB); | |
| inDag[succBB] = childNode; | |
| } | |
| addEdge(currentNode, childNode, duplicateCount); | |
| dfsStack.push(childNode); | |
| } | |
| } | |
| // The weight on each edge is the increment required along any path that | |
| // contains that edge. | |
| void BallLarusDag::calculatePathNumbersFrom(BallLarusNode* node) { | |
| if(node == getExit()) | |
| // The Exit node must be base case | |
| node->setNumberPaths(1); | |
| else { | |
| unsigned sumPaths = 0; | |
| BallLarusNode* succNode; | |
| for(BLEdgeIterator succ = node->succBegin(), end = node->succEnd(); | |
| succ != end; succ++) { | |
| if( (*succ)->getType() == BallLarusEdge::BACKEDGE || | |
| (*succ)->getType() == BallLarusEdge::SPLITEDGE ) | |
| continue; | |
| (*succ)->setWeight(sumPaths); | |
| succNode = (*succ)->getTarget(); | |
| if( !succNode->getNumberPaths() ) | |
| return; | |
| sumPaths += succNode->getNumberPaths(); | |
| } | |
| node->setNumberPaths(sumPaths); | |
| } | |
| } | |
| // Allows subclasses to determine which type of Node is created. | |
| // Override this method to produce subclasses of BallLarusNode if | |
| // necessary. The destructor of BallLarusDag will call free on each | |
| // pointer created. | |
| BallLarusNode* BallLarusDag::createNode(BasicBlock* BB) { | |
| return( new BallLarusNode(BB) ); | |
| } | |
| // Allows subclasses to determine which type of Edge is created. | |
| // Override this method to produce subclasses of BallLarusEdge if | |
| // necessary. The destructor of BallLarusDag will call free on each | |
| // pointer created. | |
| BallLarusEdge* BallLarusDag::createEdge(BallLarusNode* source, | |
| BallLarusNode* target, | |
| unsigned duplicateCount) { | |
| return( new BallLarusEdge(source, target, duplicateCount) ); | |
| } | |
| // Proxy to node's constructor. Updates the DAG state. | |
| BallLarusNode* BallLarusDag::addNode(BasicBlock* BB) { | |
| BallLarusNode* newNode = createNode(BB); | |
| _nodes.push_back(newNode); | |
| return( newNode ); | |
| } | |
| // Proxy to edge's constructor. Updates the DAG state. | |
| BallLarusEdge* BallLarusDag::addEdge(BallLarusNode* source, | |
| BallLarusNode* target, | |
| unsigned duplicateCount) { | |
| BallLarusEdge* newEdge = createEdge(source, target, duplicateCount); | |
| _edges.push_back(newEdge); | |
| source->addSuccEdge(newEdge); | |
| target->addPredEdge(newEdge); | |
| return(newEdge); | |
| } | |
| // Adds a backedge with its phony edges. Updates the DAG state. | |
| void BallLarusDag::addBackedge(BallLarusNode* source, BallLarusNode* target, | |
| unsigned duplicateCount) { | |
| BallLarusEdge* childEdge = addEdge(source, target, duplicateCount); | |
| childEdge->setType(BallLarusEdge::BACKEDGE); | |
| childEdge->setPhonyRoot(addEdge(getRoot(), target,0)); | |
| childEdge->setPhonyExit(addEdge(source, getExit(),0)); | |
| childEdge->getPhonyRoot()->setRealEdge(childEdge); | |
| childEdge->getPhonyRoot()->setType(BallLarusEdge::BACKEDGE_PHONY); | |
| childEdge->getPhonyExit()->setRealEdge(childEdge); | |
| childEdge->getPhonyExit()->setType(BallLarusEdge::BACKEDGE_PHONY); | |
| _backEdges.push_back(childEdge); | |
| } |