1 //===--Graph.cpp--- implements Graph class ---------------- ------*- C++ -*--=//
3 // This implements Graph for helping in trace generation
4 // This graph gets used by "ProfilePaths" class
6 //===----------------------------------------------------------------------===//
9 #include "llvm/BasicBlock.h"
19 static const graphListElement *findNodeInList(const Graph::nodeList &NL,
21 for(Graph::nodeList::const_iterator NI = NL.begin(), NE=NL.end(); NI != NE;
23 if (*NI->element== *N)
28 static graphListElement *findNodeInList(Graph::nodeList &NL, Node *N) {
29 for(Graph::nodeList::iterator NI = NL.begin(), NE=NL.end(); NI != NE; ++NI)
30 if (*NI->element== *N)
35 //graph constructor with root and exit specified
36 Graph::Graph(std::set<Node*> n, std::set<Edge> e,
40 for(set<Node* >::iterator x=n.begin(), en=n.end(); x!=en; ++x)
41 nodes[*x] = list<graphListElement>();
43 for(set<Edge >::iterator x=e.begin(), en=e.end(); x!=en; ++x){
46 nodes[ee.getFirst()].push_front(graphListElement(ee.getSecond(),w));
51 //check whether graph has an edge
52 //having an edge simply means that there is an edge in the graph
53 //which has same endpoints as the given edge
54 bool Graph::hasEdge(Edge ed) const{
58 nodeList nli=getNodeList(ed.getFirst());
59 Node *nd2=ed.getSecond();
61 return (findNodeInList(nli,nd2)!=NULL);
66 //check whether graph has an edge, with a given wt
67 //having an edge simply means that there is an edge in the graph
68 //which has same endpoints as the given edge
69 //This function checks, moreover, that the wt of edge matches too
70 bool Graph::hasEdgeAndWt(Edge ed) const{
74 Node *nd2=ed.getSecond();
75 nodeList nli=getNodeList(ed.getFirst());
77 for(nodeList::iterator NI=nli.begin(), NE=nli.end(); NI!=NE; ++NI)
78 if(*NI->element == *nd2 && ed.getWeight()==NI->weight)
85 void Graph::addNode(Node *nd){
86 list<Node *> lt=getAllNodes();
88 for(list<Node *>::iterator LI=lt.begin(), LE=lt.end(); LI!=LE;++LI){
93 nodes[nd] = list<graphListElement>();
97 //this adds an edge ONLY when
98 //the edge to be added doesn not already exist
99 //we "equate" two edges here only with their
101 void Graph::addEdge(Edge ed, int w){
102 nodeList &ndList = nodes[ed.getFirst()];
103 Node *nd2=ed.getSecond();
105 if(findNodeInList(nodes[ed.getFirst()], nd2))
108 ndList.push_front(graphListElement(nd2,w));
111 //add an edge EVEN IF such an edge already exists
112 //this may make a multi-graph
113 //which does happen when we add dummy edges
114 //to the graph, for compensating for back-edges
115 void Graph::addEdgeForce(Edge ed){
116 nodes[ed.getFirst()].push_front(graphListElement(ed.getSecond(),
121 //Note that it removes just one edge,
122 //the first edge that is encountered
123 void Graph::removeEdge(Edge ed){
124 nodeList &ndList = nodes[ed.getFirst()];
125 Node &nd2 = *ed.getSecond();
127 for(nodeList::iterator NI=ndList.begin(), NE=ndList.end(); NI!=NE ;++NI) {
128 if(*NI->element == nd2) {
135 //set the weight of an edge
136 void Graph::setWeight(Edge ed){
137 graphListElement *El = findNodeInList(nodes[ed.getFirst()], ed.getSecond());
139 El->weight=ed.getWeight();
144 //get the list of successor nodes
145 list<Node *> Graph::getSuccNodes(Node *nd) const {
146 nodeMapTy::const_iterator nli = nodes.find(nd);
147 assert(nli != nodes.end() && "Node must be in nodes map");
148 const nodeList &nl = nli->second;
151 for(nodeList::const_iterator NI=nl.begin(), NE=nl.end(); NI!=NE; ++NI)
152 lt.push_back(NI->element);
157 //get the list of predecessor nodes
158 list<Node *> Graph::getPredNodes(Node *nd) const{
160 for(nodeMapTy::const_iterator EI=nodes.begin(), EE=nodes.end(); EI!=EE ;++EI){
161 Node *lnode=EI->first;
162 const nodeList &nl = getNodeList(lnode);
164 const graphListElement *N = findNodeInList(nl, nd);
165 if (N) lt.push_back(lnode);
170 //get the list of all the vertices in graph
171 list<Node *> Graph::getAllNodes() const{
173 for(nodeMapTy::const_iterator x=nodes.begin(), en=nodes.end(); x != en; ++x)
174 lt.push_back(x->first);
180 //class to compare two nodes in graph
181 //based on their wt: this is used in
182 //finding the maximal spanning tree
183 struct compare_nodes {
184 bool operator()(Node *n1, Node *n2){
185 return n1->getWeight() < n2->getWeight();
190 static void printNode(Node *nd){
191 cerr<<"Node:"<<nd->getElement()->getName()<<"\n";
194 //Get the Maximal spanning tree (also a graph)
196 Graph* Graph::getMaxSpanningTree(){
197 //assume connected graph
199 Graph *st=new Graph();//max spanning tree, undirected edges
200 int inf=9999999;//largest key
201 list<Node *> lt = getAllNodes();
203 //initially put all vertices in vector vt
205 //wt(others)=infinity
208 //pull out u: a vertex frm vt of min wt
209 //for all vertices w in vt,
210 //if wt(w) greater than
211 //the wt(u->w), then assign
212 //wt(w) to be wt(u->w).
214 //make parent(u)=w in the spanning tree
215 //keep pulling out vertices from vt till it is empty
219 map<Node*, Node* > parent;
220 map<Node*, int > ed_weight;
222 //initialize: wt(root)=0, wt(others)=infinity
223 //parent(root)=NULL, parent(others) not defined (but not null)
224 for(list<Node *>::iterator LI=lt.begin(), LE=lt.end(); LI!=LE; ++LI){
226 if(*thisNode == *getRoot()){
227 thisNode->setWeight(0);
228 parent[thisNode]=NULL;
229 ed_weight[thisNode]=0;
232 thisNode->setWeight(inf);
234 st->addNode(thisNode);//add all nodes to spanning tree
235 //we later need to assign edges in the tree
236 vt.push_back(thisNode); //pushed all nodes in vt
239 //keep pulling out vertex of min wt from vt
241 Node *u=*(min_element(vt.begin(), vt.end(), compare_nodes()));
242 DEBUG(cerr<<"popped wt"<<(u)->getWeight()<<"\n";
245 if(parent[u]!=NULL){ //so not root
246 Edge edge(parent[u],u, ed_weight[u]); //assign edge in spanning tree
247 st->addEdge(edge,ed_weight[u]);
249 DEBUG(cerr<<"added:\n";
256 for(vector<Node *>::iterator VI=vt.begin(), VE=vt.end(); VI!=VE; ++VI){
263 //assign wt(v) to all adjacent vertices v of u
265 Graph::nodeList nl=getNodeList(u);
266 for(nodeList::iterator NI=nl.begin(), NE=nl.end(); NI!=NE; ++NI){
268 int weight=-NI->weight;
269 //check if v is in vt
271 for(vector<Node *>::iterator VI=vt.begin(), VE=vt.end(); VI!=VE; ++VI){
277 DEBUG(cerr<<"wt:v->wt"<<weight<<":"<<v->getWeight()<<"\n";
278 printNode(v);cerr<<"node wt:"<<(*v).weight<<"\n");
280 //so if v in in vt, change wt(v) to wt(u->v)
281 //only if wt(u->v)<wt(v)
282 if(contains && weight<v->getWeight()){
285 v->setWeight(weight);
287 DEBUG(cerr<<v->getWeight()<<":Set weight------\n";
289 printEdge(Edge(u,v,weight)));
296 //print the graph (for debugging)
297 void Graph::printGraph(){
298 list<Node *> lt=getAllNodes();
299 cerr<<"Graph---------------------\n";
300 for(list<Node *>::iterator LI=lt.begin(), LE=lt.end(); LI!=LE; ++LI){
301 cerr<<((*LI)->getElement())->getName()<<"->";
302 Graph::nodeList nl=getNodeList(*LI);
303 for(Graph::nodeList::iterator NI=nl.begin(), NE=nl.end(); NI!=NE; ++NI){
304 cerr<<":"<<"("<<(NI->element->getElement())
305 ->getName()<<":"<<NI->element->getWeight()<<","<<NI->weight<<")";
312 //get a list of nodes in the graph
313 //in r-topological sorted order
314 //note that we assumed graph to be connected
315 list<Node *> Graph::reverseTopologicalSort() const{
316 list <Node *> toReturn;
317 list<Node *> lt=getAllNodes();
318 for(list<Node *>::iterator LI=lt.begin(), LE=lt.end(); LI!=LE; ++LI){
319 if((*LI)->getWeight()!=GREY && (*LI)->getWeight()!=BLACK)
320 DFS_Visit(*LI, toReturn);
325 //a private method for doing DFS traversal of graph
326 //this is used in determining the reverse topological sort
328 void Graph::DFS_Visit(Node *nd, list<Node *> &toReturn) const {
330 list<Node *> lt=getSuccNodes(nd);
331 for(list<Node *>::iterator LI=lt.begin(), LE=lt.end(); LI!=LE; ++LI){
332 if((*LI)->getWeight()!=GREY && (*LI)->getWeight()!=BLACK)
333 DFS_Visit(*LI, toReturn);
335 toReturn.push_back(nd);
338 //Ordinarily, the graph is directional
339 //this converts the graph into an
340 //undirectional graph
341 //This is done by adding an edge
342 //v->u for all existing edges u->v
343 void Graph::makeUnDirectional(){
344 list<Node* > allNodes=getAllNodes();
345 for(list<Node *>::iterator NI=allNodes.begin(), NE=allNodes.end(); NI!=NE;
347 nodeList nl=getNodeList(*NI);
348 for(nodeList::iterator NLI=nl.begin(), NLE=nl.end(); NLI!=NLE; ++NLI){
349 Edge ed(NLI->element, *NI, NLI->weight);
350 if(!hasEdgeAndWt(ed)){
351 DEBUG(cerr<<"######doesn't hv\n";
359 //reverse the sign of weights on edges
360 //this way, max-spanning tree could be obtained
361 //usin min-spanning tree, and vice versa
362 void Graph::reverseWts(){
363 list<Node *> allNodes=getAllNodes();
364 for(list<Node *>::iterator NI=allNodes.begin(), NE=allNodes.end(); NI!=NE;
366 nodeList node_list=getNodeList(*NI);
367 for(nodeList::iterator NLI=nodes[*NI].begin(), NLE=nodes[*NI].end();
369 NLI->weight=-NLI->weight;
374 //getting the backedges in a graph
375 //Its a variation of DFS to get the backedges in the graph
376 //We get back edges by associating a time
377 //and a color with each vertex.
378 //The time of a vertex is the time when it was first visited
379 //The color of a vertex is initially WHITE,
380 //Changes to GREY when it is first visited,
381 //and changes to BLACK when ALL its neighbors
383 //So we have a back edge when we meet a successor of
384 //a node with smaller time, and GREY color
385 void Graph::getBackEdges(vector<Edge > &be) const{
386 map<Node *, Color > color;
388 list<Node *> allNodes=getAllNodes();
390 for(list<Node *>::const_iterator NI=allNodes.begin(), NE=allNodes.end();
392 if(color[*NI]!=GREY && color[*NI]!=BLACK)
393 getBackEdgesVisit(*NI, be, color, d, time);
397 //helper function to get back edges: it is called by
398 //the "getBackEdges" function above
399 void Graph::getBackEdgesVisit(Node *u, vector<Edge > &be,
400 map<Node *, Color > &color,
401 map<Node *, int > &d, int &time) const{
405 list<Node *> succ_list=getSuccNodes(u);
407 for(list<Node *>::const_iterator v=succ_list.begin(), ve=succ_list.end();
409 if(color[*v]!=GREY && color[*v]!=BLACK){
410 getBackEdgesVisit(*v, be, color, d, time);
413 //now checking for d and f vals
415 //so v is ancestor of u if time of u > time of v
417 Edge *ed=new Edge(u, *v);
418 if (!(*u == *getExit() && **v == *getRoot()))
419 be.push_back(*ed); // choose the forward edges
423 color[u]=BLACK;//done with visiting the node and its neighbors