| //===-- Graph.cpp - Implements Graph class --------------------------------===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file was developed by the LLVM research group and is distributed under |
| // the University of Illinois Open Source License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This implements Graph for helping in trace generation This graph gets used by |
| // "ProfilePaths" class. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "Graph.h" |
| #include "llvm/iTerminators.h" |
| #include "Support/Debug.h" |
| #include <algorithm> |
| |
| using std::vector; |
| |
| namespace llvm { |
| |
| const graphListElement *findNodeInList(const Graph::nodeList &NL, |
| Node *N) { |
| for(Graph::nodeList::const_iterator NI = NL.begin(), NE=NL.end(); NI != NE; |
| ++NI) |
| if (*NI->element== *N) |
| return &*NI; |
| return 0; |
| } |
| |
| graphListElement *findNodeInList(Graph::nodeList &NL, Node *N) { |
| for(Graph::nodeList::iterator NI = NL.begin(), NE=NL.end(); NI != NE; ++NI) |
| if (*NI->element== *N) |
| return &*NI; |
| return 0; |
| } |
| |
| //graph constructor with root and exit specified |
| Graph::Graph(std::vector<Node*> n, std::vector<Edge> e, |
| Node *rt, Node *lt){ |
| strt=rt; |
| ext=lt; |
| for(vector<Node* >::iterator x=n.begin(), en=n.end(); x!=en; ++x) |
| //nodes[*x] = list<graphListElement>(); |
| nodes[*x] = vector<graphListElement>(); |
| |
| for(vector<Edge >::iterator x=e.begin(), en=e.end(); x!=en; ++x){ |
| Edge ee=*x; |
| int w=ee.getWeight(); |
| //nodes[ee.getFirst()].push_front(graphListElement(ee.getSecond(),w, ee.getRandId())); |
| nodes[ee.getFirst()].push_back(graphListElement(ee.getSecond(),w, ee.getRandId())); |
| } |
| |
| } |
| |
| //sorting edgelist, called by backEdgeVist ONLY!!! |
| Graph::nodeList &Graph::sortNodeList(Node *par, nodeList &nl, vector<Edge> &be){ |
| assert(par && "null node pointer"); |
| BasicBlock *bbPar = par->getElement(); |
| |
| if(nl.size()<=1) return nl; |
| if(getExit() == par) return nl; |
| |
| for(nodeList::iterator NLI = nl.begin(), NLE = nl.end()-1; NLI != NLE; ++NLI){ |
| nodeList::iterator min = NLI; |
| for(nodeList::iterator LI = NLI+1, LE = nl.end(); LI!=LE; ++LI){ |
| //if LI < min, min = LI |
| if(min->element->getElement() == LI->element->getElement() && |
| min->element == getExit()){ |
| |
| //same successors: so might be exit??? |
| //if it is exit, then see which is backedge |
| //check if LI is a left back edge! |
| |
| TerminatorInst *tti = par->getElement()->getTerminator(); |
| BranchInst *ti = cast<BranchInst>(tti); |
| |
| assert(ti && "not a branch"); |
| assert(ti->getNumSuccessors()==2 && "less successors!"); |
| |
| BasicBlock *tB = ti->getSuccessor(0); |
| BasicBlock *fB = ti->getSuccessor(1); |
| //so one of LI or min must be back edge! |
| //Algo: if succ(0)!=LI (and so !=min) then succ(0) is backedge |
| //and then see which of min or LI is backedge |
| //THEN if LI is in be, then min=LI |
| if(LI->element->getElement() != tB){//so backedge must be made min! |
| for(vector<Edge>::iterator VBEI = be.begin(), VBEE = be.end(); |
| VBEI != VBEE; ++VBEI){ |
| if(VBEI->getRandId() == LI->randId){ |
| min = LI; |
| break; |
| } |
| else if(VBEI->getRandId() == min->randId) |
| break; |
| } |
| } |
| else{// if(LI->element->getElement() != fB) |
| for(vector<Edge>::iterator VBEI = be.begin(), VBEE = be.end(); |
| VBEI != VBEE; ++VBEI){ |
| if(VBEI->getRandId() == min->randId){ |
| min = LI; |
| break; |
| } |
| else if(VBEI->getRandId() == LI->randId) |
| break; |
| } |
| } |
| } |
| |
| else if (min->element->getElement() != LI->element->getElement()){ |
| TerminatorInst *tti = par->getElement()->getTerminator(); |
| BranchInst *ti = cast<BranchInst>(tti); |
| assert(ti && "not a branch"); |
| |
| if(ti->getNumSuccessors()<=1) continue; |
| |
| assert(ti->getNumSuccessors()==2 && "less successors!"); |
| |
| BasicBlock *tB = ti->getSuccessor(0); |
| BasicBlock *fB = ti->getSuccessor(1); |
| |
| if(tB == LI->element->getElement() || fB == min->element->getElement()) |
| min = LI; |
| } |
| } |
| |
| graphListElement tmpElmnt = *min; |
| *min = *NLI; |
| *NLI = tmpElmnt; |
| } |
| return nl; |
| } |
| |
| //check whether graph has an edge |
| //having an edge simply means that there is an edge in the graph |
| //which has same endpoints as the given edge |
| bool Graph::hasEdge(Edge ed){ |
| if(ed.isNull()) |
| return false; |
| |
| nodeList &nli= nodes[ed.getFirst()]; //getNodeList(ed.getFirst()); |
| Node *nd2=ed.getSecond(); |
| |
| return (findNodeInList(nli,nd2)!=NULL); |
| |
| } |
| |
| |
| //check whether graph has an edge, with a given wt |
| //having an edge simply means that there is an edge in the graph |
| //which has same endpoints as the given edge |
| //This function checks, moreover, that the wt of edge matches too |
| bool Graph::hasEdgeAndWt(Edge ed){ |
| if(ed.isNull()) |
| return false; |
| |
| Node *nd2=ed.getSecond(); |
| nodeList &nli = nodes[ed.getFirst()];//getNodeList(ed.getFirst()); |
| |
| for(nodeList::iterator NI=nli.begin(), NE=nli.end(); NI!=NE; ++NI) |
| if(*NI->element == *nd2 && ed.getWeight()==NI->weight) |
| return true; |
| |
| return false; |
| } |
| |
| //add a node |
| void Graph::addNode(Node *nd){ |
| vector<Node *> lt=getAllNodes(); |
| |
| for(vector<Node *>::iterator LI=lt.begin(), LE=lt.end(); LI!=LE;++LI){ |
| if(**LI==*nd) |
| return; |
| } |
| //chng |
| nodes[nd] =vector<graphListElement>(); //list<graphListElement>(); |
| } |
| |
| //add an edge |
| //this adds an edge ONLY when |
| //the edge to be added does not already exist |
| //we "equate" two edges here only with their |
| //end points |
| void Graph::addEdge(Edge ed, int w){ |
| nodeList &ndList = nodes[ed.getFirst()]; |
| Node *nd2=ed.getSecond(); |
| |
| if(findNodeInList(nodes[ed.getFirst()], nd2)) |
| return; |
| |
| //ndList.push_front(graphListElement(nd2,w, ed.getRandId())); |
| ndList.push_back(graphListElement(nd2,w, ed.getRandId()));//chng |
| //sortNodeList(ed.getFirst(), ndList); |
| |
| //sort(ndList.begin(), ndList.end(), NodeListSort()); |
| } |
| |
| //add an edge EVEN IF such an edge already exists |
| //this may make a multi-graph |
| //which does happen when we add dummy edges |
| //to the graph, for compensating for back-edges |
| void Graph::addEdgeForce(Edge ed){ |
| //nodes[ed.getFirst()].push_front(graphListElement(ed.getSecond(), |
| //ed.getWeight(), ed.getRandId())); |
| nodes[ed.getFirst()].push_back |
| (graphListElement(ed.getSecond(), ed.getWeight(), ed.getRandId())); |
| |
| //sortNodeList(ed.getFirst(), nodes[ed.getFirst()]); |
| //sort(nodes[ed.getFirst()].begin(), nodes[ed.getFirst()].end(), NodeListSort()); |
| } |
| |
| //remove an edge |
| //Note that it removes just one edge, |
| //the first edge that is encountered |
| void Graph::removeEdge(Edge ed){ |
| nodeList &ndList = nodes[ed.getFirst()]; |
| Node &nd2 = *ed.getSecond(); |
| |
| for(nodeList::iterator NI=ndList.begin(), NE=ndList.end(); NI!=NE ;++NI) { |
| if(*NI->element == nd2) { |
| ndList.erase(NI); |
| break; |
| } |
| } |
| } |
| |
| //remove an edge with a given wt |
| //Note that it removes just one edge, |
| //the first edge that is encountered |
| void Graph::removeEdgeWithWt(Edge ed){ |
| nodeList &ndList = nodes[ed.getFirst()]; |
| Node &nd2 = *ed.getSecond(); |
| |
| for(nodeList::iterator NI=ndList.begin(), NE=ndList.end(); NI!=NE ;++NI) { |
| if(*NI->element == nd2 && NI->weight==ed.getWeight()) { |
| ndList.erase(NI); |
| break; |
| } |
| } |
| } |
| |
| //set the weight of an edge |
| void Graph::setWeight(Edge ed){ |
| graphListElement *El = findNodeInList(nodes[ed.getFirst()], ed.getSecond()); |
| if (El) |
| El->weight=ed.getWeight(); |
| } |
| |
| |
| |
| //get the list of successor nodes |
| vector<Node *> Graph::getSuccNodes(Node *nd){ |
| nodeMapTy::const_iterator nli = nodes.find(nd); |
| assert(nli != nodes.end() && "Node must be in nodes map"); |
| const nodeList &nl = getNodeList(nd);//getSortedNodeList(nd); |
| |
| vector<Node *> lt; |
| for(nodeList::const_iterator NI=nl.begin(), NE=nl.end(); NI!=NE; ++NI) |
| lt.push_back(NI->element); |
| |
| return lt; |
| } |
| |
| //get the number of outgoing edges |
| int Graph::getNumberOfOutgoingEdges(Node *nd) const { |
| nodeMapTy::const_iterator nli = nodes.find(nd); |
| assert(nli != nodes.end() && "Node must be in nodes map"); |
| const nodeList &nl = nli->second; |
| |
| int count=0; |
| for(nodeList::const_iterator NI=nl.begin(), NE=nl.end(); NI!=NE; ++NI) |
| count++; |
| |
| return count; |
| } |
| |
| //get the list of predecessor nodes |
| vector<Node *> Graph::getPredNodes(Node *nd){ |
| vector<Node *> lt; |
| for(nodeMapTy::const_iterator EI=nodes.begin(), EE=nodes.end(); EI!=EE ;++EI){ |
| Node *lnode=EI->first; |
| const nodeList &nl = getNodeList(lnode); |
| |
| const graphListElement *N = findNodeInList(nl, nd); |
| if (N) lt.push_back(lnode); |
| } |
| return lt; |
| } |
| |
| //get the number of predecessor nodes |
| int Graph::getNumberOfIncomingEdges(Node *nd){ |
| int count=0; |
| for(nodeMapTy::const_iterator EI=nodes.begin(), EE=nodes.end(); EI!=EE ;++EI){ |
| Node *lnode=EI->first; |
| const nodeList &nl = getNodeList(lnode); |
| for(Graph::nodeList::const_iterator NI = nl.begin(), NE=nl.end(); NI != NE; |
| ++NI) |
| if (*NI->element== *nd) |
| count++; |
| } |
| return count; |
| } |
| |
| //get the list of all the vertices in graph |
| vector<Node *> Graph::getAllNodes() const{ |
| vector<Node *> lt; |
| for(nodeMapTy::const_iterator x=nodes.begin(), en=nodes.end(); x != en; ++x) |
| lt.push_back(x->first); |
| |
| return lt; |
| } |
| |
| //get the list of all the vertices in graph |
| vector<Node *> Graph::getAllNodes(){ |
| vector<Node *> lt; |
| for(nodeMapTy::const_iterator x=nodes.begin(), en=nodes.end(); x != en; ++x) |
| lt.push_back(x->first); |
| |
| return lt; |
| } |
| |
| //class to compare two nodes in graph |
| //based on their wt: this is used in |
| //finding the maximal spanning tree |
| struct compare_nodes { |
| bool operator()(Node *n1, Node *n2){ |
| return n1->getWeight() < n2->getWeight(); |
| } |
| }; |
| |
| |
| static void printNode(Node *nd){ |
| std::cerr<<"Node:"<<nd->getElement()->getName()<<"\n"; |
| } |
| |
| //Get the Maximal spanning tree (also a graph) |
| //of the graph |
| Graph* Graph::getMaxSpanningTree(){ |
| //assume connected graph |
| |
| Graph *st=new Graph();//max spanning tree, undirected edges |
| int inf=9999999;//largest key |
| vector<Node *> lt = getAllNodes(); |
| |
| //initially put all vertices in vector vt |
| //assign wt(root)=0 |
| //wt(others)=infinity |
| // |
| //now: |
| //pull out u: a vertex frm vt of min wt |
| //for all vertices w in vt, |
| //if wt(w) greater than |
| //the wt(u->w), then assign |
| //wt(w) to be wt(u->w). |
| // |
| //make parent(u)=w in the spanning tree |
| //keep pulling out vertices from vt till it is empty |
| |
| vector<Node *> vt; |
| |
| std::map<Node*, Node* > parent; |
| std::map<Node*, int > ed_weight; |
| |
| //initialize: wt(root)=0, wt(others)=infinity |
| //parent(root)=NULL, parent(others) not defined (but not null) |
| for(vector<Node *>::iterator LI=lt.begin(), LE=lt.end(); LI!=LE; ++LI){ |
| Node *thisNode=*LI; |
| if(*thisNode == *getRoot()){ |
| thisNode->setWeight(0); |
| parent[thisNode]=NULL; |
| ed_weight[thisNode]=0; |
| } |
| else{ |
| thisNode->setWeight(inf); |
| } |
| st->addNode(thisNode);//add all nodes to spanning tree |
| //we later need to assign edges in the tree |
| vt.push_back(thisNode); //pushed all nodes in vt |
| } |
| |
| //keep pulling out vertex of min wt from vt |
| while(!vt.empty()){ |
| Node *u=*(min_element(vt.begin(), vt.end(), compare_nodes())); |
| DEBUG(std::cerr<<"popped wt"<<(u)->getWeight()<<"\n"; |
| printNode(u)); |
| |
| if(parent[u]!=NULL){ //so not root |
| Edge edge(parent[u],u, ed_weight[u]); //assign edge in spanning tree |
| st->addEdge(edge,ed_weight[u]); |
| |
| DEBUG(std::cerr<<"added:\n"; |
| printEdge(edge)); |
| } |
| |
| //vt.erase(u); |
| |
| //remove u frm vt |
| for(vector<Node *>::iterator VI=vt.begin(), VE=vt.end(); VI!=VE; ++VI){ |
| if(**VI==*u){ |
| vt.erase(VI); |
| break; |
| } |
| } |
| |
| //assign wt(v) to all adjacent vertices v of u |
| //only if v is in vt |
| Graph::nodeList &nl = getNodeList(u); |
| for(nodeList::iterator NI=nl.begin(), NE=nl.end(); NI!=NE; ++NI){ |
| Node *v=NI->element; |
| int weight=-NI->weight; |
| //check if v is in vt |
| bool contains=false; |
| for(vector<Node *>::iterator VI=vt.begin(), VE=vt.end(); VI!=VE; ++VI){ |
| if(**VI==*v){ |
| contains=true; |
| break; |
| } |
| } |
| DEBUG(std::cerr<<"wt:v->wt"<<weight<<":"<<v->getWeight()<<"\n"; |
| printNode(v);std::cerr<<"node wt:"<<(*v).weight<<"\n"); |
| |
| //so if v in in vt, change wt(v) to wt(u->v) |
| //only if wt(u->v)<wt(v) |
| if(contains && weight<v->getWeight()){ |
| parent[v]=u; |
| ed_weight[v]=weight; |
| v->setWeight(weight); |
| |
| DEBUG(std::cerr<<v->getWeight()<<":Set weight------\n"; |
| printGraph(); |
| printEdge(Edge(u,v,weight))); |
| } |
| } |
| } |
| return st; |
| } |
| |
| //print the graph (for debugging) |
| void Graph::printGraph(){ |
| vector<Node *> lt=getAllNodes(); |
| std::cerr<<"Graph---------------------\n"; |
| for(vector<Node *>::iterator LI=lt.begin(), LE=lt.end(); LI!=LE; ++LI){ |
| std::cerr<<((*LI)->getElement())->getName()<<"->"; |
| Graph::nodeList &nl = getNodeList(*LI); |
| for(Graph::nodeList::iterator NI=nl.begin(), NE=nl.end(); NI!=NE; ++NI){ |
| std::cerr<<":"<<"("<<(NI->element->getElement()) |
| ->getName()<<":"<<NI->element->getWeight()<<","<<NI->weight<<")"; |
| } |
| std::cerr<<"--------\n"; |
| } |
| } |
| |
| |
| //get a list of nodes in the graph |
| //in r-topological sorted order |
| //note that we assumed graph to be connected |
| vector<Node *> Graph::reverseTopologicalSort(){ |
| vector <Node *> toReturn; |
| vector<Node *> lt=getAllNodes(); |
| for(vector<Node *>::iterator LI=lt.begin(), LE=lt.end(); LI!=LE; ++LI){ |
| if((*LI)->getWeight()!=GREY && (*LI)->getWeight()!=BLACK) |
| DFS_Visit(*LI, toReturn); |
| } |
| |
| return toReturn; |
| } |
| |
| //a private method for doing DFS traversal of graph |
| //this is used in determining the reverse topological sort |
| //of the graph |
| void Graph::DFS_Visit(Node *nd, vector<Node *> &toReturn){ |
| nd->setWeight(GREY); |
| vector<Node *> lt=getSuccNodes(nd); |
| for(vector<Node *>::iterator LI=lt.begin(), LE=lt.end(); LI!=LE; ++LI){ |
| if((*LI)->getWeight()!=GREY && (*LI)->getWeight()!=BLACK) |
| DFS_Visit(*LI, toReturn); |
| } |
| toReturn.push_back(nd); |
| } |
| |
| //Ordinarily, the graph is directional |
| //this converts the graph into an |
| //undirectional graph |
| //This is done by adding an edge |
| //v->u for all existing edges u->v |
| void Graph::makeUnDirectional(){ |
| vector<Node* > allNodes=getAllNodes(); |
| for(vector<Node *>::iterator NI=allNodes.begin(), NE=allNodes.end(); NI!=NE; |
| ++NI) { |
| nodeList &nl = getNodeList(*NI); |
| for(nodeList::iterator NLI=nl.begin(), NLE=nl.end(); NLI!=NLE; ++NLI){ |
| Edge ed(NLI->element, *NI, NLI->weight); |
| if(!hasEdgeAndWt(ed)){ |
| DEBUG(std::cerr<<"######doesn't hv\n"; |
| printEdge(ed)); |
| addEdgeForce(ed); |
| } |
| } |
| } |
| } |
| |
| //reverse the sign of weights on edges |
| //this way, max-spanning tree could be obtained |
| //using min-spanning tree, and vice versa |
| void Graph::reverseWts(){ |
| vector<Node *> allNodes=getAllNodes(); |
| for(vector<Node *>::iterator NI=allNodes.begin(), NE=allNodes.end(); NI!=NE; |
| ++NI) { |
| nodeList &node_list = getNodeList(*NI); |
| for(nodeList::iterator NLI=nodes[*NI].begin(), NLE=nodes[*NI].end(); |
| NLI!=NLE; ++NLI) |
| NLI->weight=-NLI->weight; |
| } |
| } |
| |
| |
| //getting the backedges in a graph |
| //Its a variation of DFS to get the backedges in the graph |
| //We get back edges by associating a time |
| //and a color with each vertex. |
| //The time of a vertex is the time when it was first visited |
| //The color of a vertex is initially WHITE, |
| //Changes to GREY when it is first visited, |
| //and changes to BLACK when ALL its neighbors |
| //have been visited |
| //So we have a back edge when we meet a successor of |
| //a node with smaller time, and GREY color |
| void Graph::getBackEdges(vector<Edge > &be, std::map<Node *, int> &d){ |
| std::map<Node *, Color > color; |
| int time=0; |
| |
| getBackEdgesVisit(getRoot(), be, color, d, time); |
| } |
| |
| //helper function to get back edges: it is called by |
| //the "getBackEdges" function above |
| void Graph::getBackEdgesVisit(Node *u, vector<Edge > &be, |
| std::map<Node *, Color > &color, |
| std::map<Node *, int > &d, int &time) { |
| color[u]=GREY; |
| time++; |
| d[u]=time; |
| |
| vector<graphListElement> &succ_list = getNodeList(u); |
| |
| for(vector<graphListElement>::iterator vl=succ_list.begin(), |
| ve=succ_list.end(); vl!=ve; ++vl){ |
| Node *v=vl->element; |
| if(color[v]!=GREY && color[v]!=BLACK){ |
| getBackEdgesVisit(v, be, color, d, time); |
| } |
| |
| //now checking for d and f vals |
| if(color[v]==GREY){ |
| //so v is ancestor of u if time of u > time of v |
| if(d[u] >= d[v]){ |
| Edge *ed=new Edge(u, v,vl->weight, vl->randId); |
| if (!(*u == *getExit() && *v == *getRoot())) |
| be.push_back(*ed); // choose the forward edges |
| } |
| } |
| } |
| color[u]=BLACK;//done with visiting the node and its neighbors |
| } |
| |
| } // End llvm namespace |