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