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