blob: 206af1f682d502647967fc12f3884e1e4c9dd214 [file] [log] [blame]
Anand Shuklad3d1fcd2002-02-26 18:58:39 +00001//===--Graph.cpp--- implements Graph class ---------------- ------*- C++ -*--=//
2//
3// This implements Graph for helping in trace generation
Chris Lattner5328c6f2002-02-26 19:40:28 +00004// This graph gets used by "ProfilePaths" class
Anand Shuklad3d1fcd2002-02-26 18:58:39 +00005//
6//===----------------------------------------------------------------------===//
7
8#include "Graph.h"
9#include "llvm/BasicBlock.h"
10#include <algorithm>
Chris Lattner5328c6f2002-02-26 19:40:28 +000011#include <iostream>
12
13using std::list;
14using std::set;
15using std::map;
16using std::vector;
17using std::cerr;
Anand Shuklad3d1fcd2002-02-26 18:58:39 +000018
19static const graphListElement *findNodeInList(const Graph::nodeList &NL,
20 Node *N) {
21 for(Graph::nodeList::const_iterator NI = NL.begin(), NE=NL.end(); NI != NE;
22 ++NI)
23 if (*NI->element== *N)
24 return &*NI;
25 return 0;
26}
27
28static 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)
31 return &*NI;
32 return 0;
33}
34
35//graph constructor with root and exit specified
36Graph::Graph(std::set<Node*> n, std::set<Edge> e,
37 Node *rt, Node *lt){
38 strt=rt;
39 ext=lt;
40 for(set<Node* >::iterator x=n.begin(), en=n.end(); x!=en; ++x)
41 nodes[*x] = list<graphListElement>();
42
43 for(set<Edge >::iterator x=e.begin(), en=e.end(); x!=en; ++x){
44 Edge ee=*x;
45 int w=ee.getWeight();
46 nodes[ee.getFirst()].push_front(graphListElement(ee.getSecond(),w));
47 }
48
49}
50
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
54bool Graph::hasEdge(Edge ed) const{
55 if(ed.isNull())
56 return false;
57
58 nodeList nli=getNodeList(ed.getFirst());
59 Node *nd2=ed.getSecond();
60
61 return (findNodeInList(nli,nd2)!=NULL);
62
63}
64
65
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
70bool Graph::hasEdgeAndWt(Edge ed) const{
71 if(ed.isNull())
72 return false;
73
74 Node *nd2=ed.getSecond();
75 nodeList nli=getNodeList(ed.getFirst());
76
77 for(nodeList::iterator NI=nli.begin(), NE=nli.end(); NI!=NE; ++NI)
78 if(*NI->element == *nd2 && ed.getWeight()==NI->weight)
79 return true;
80
81 return false;
82}
83
84//add a node
85void Graph::addNode(Node *nd){
86 list<Node *> lt=getAllNodes();
87
88 for(list<Node *>::iterator LI=lt.begin(), LE=lt.end(); LI!=LE;++LI){
89 if(**LI==*nd)
90 return;
91 }
92
93 nodes[nd] = list<graphListElement>();
94}
95
96//add an edge
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
100//end points
101void Graph::addEdge(Edge ed, int w){
102 nodeList &ndList = nodes[ed.getFirst()];
103 Node *nd2=ed.getSecond();
104
105 if(findNodeInList(nodes[ed.getFirst()], nd2))
106 return;
107
108 ndList.push_front(graphListElement(nd2,w));
109}
110
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
115void Graph::addEdgeForce(Edge ed){
116 nodes[ed.getFirst()].push_front(graphListElement(ed.getSecond(),
117 ed.getWeight()));
118}
119
120//remove an edge
121//Note that it removes just one edge,
122//the first edge that is encountered
123void Graph::removeEdge(Edge ed){
124 nodeList &ndList = nodes[ed.getFirst()];
125 Node &nd2 = *ed.getSecond();
126
127 for(nodeList::iterator NI=ndList.begin(), NE=ndList.end(); NI!=NE ;++NI) {
128 if(*NI->element == nd2) {
129 ndList.erase(NI);
130 break;
131 }
132 }
133}
134
135//set the weight of an edge
136void Graph::setWeight(Edge ed){
137 graphListElement *El = findNodeInList(nodes[ed.getFirst()], ed.getSecond());
138 if (El)
139 El->weight=ed.getWeight();
140}
141
142
143
144//get the list of successor nodes
145list<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;
149
150 list<Node *> lt;
151 for(nodeList::const_iterator NI=nl.begin(), NE=nl.end(); NI!=NE; ++NI)
152 lt.push_back(NI->element);
153
154 return lt;
155}
156
157//get the list of predecessor nodes
158list<Node *> Graph::getPredNodes(Node *nd) const{
159 list<Node *> lt;
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);
163
164 const graphListElement *N = findNodeInList(nl, nd);
165 if (N) lt.push_back(lnode);
166 }
167 return lt;
168}
169
170//get the list of all the vertices in graph
171list<Node *> Graph::getAllNodes() const{
172 list<Node *> lt;
173 for(nodeMapTy::const_iterator x=nodes.begin(), en=nodes.end(); x != en; ++x)
174 lt.push_back(x->first);
175
176 return lt;
177}
178
179
180//class to compare two nodes in graph
181//based on their wt: this is used in
182//finding the maximal spanning tree
183struct compare_nodes {
184 bool operator()(Node *n1, Node *n2){
185 return n1->getWeight() < n2->getWeight();
186 }
187};
188
189
Chris Lattner5328c6f2002-02-26 19:40:28 +0000190static void printNode(Node *nd){
191 cerr<<"Node:"<<nd->getElement()->getName()<<"\n";
Anand Shuklad3d1fcd2002-02-26 18:58:39 +0000192}
193
194//Get the Maximal spanning tree (also a graph)
195//of the graph
196Graph* Graph::getMaxSpanningTree(){
197 //assume connected graph
198
199 Graph *st=new Graph();//max spanning tree, undirected edges
200 int inf=9999999;//largest key
201 list<Node *> lt = getAllNodes();
202
203 //initially put all vertices in vector vt
204 //assign wt(root)=0
205 //wt(others)=infinity
206 //
207 //now:
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).
213 //
214 //make parent(u)=w in the spanning tree
215 //keep pulling out vertices from vt till it is empty
216
217 vector<Node *> vt;
218
219 map<Node*, Node* > parent;
220 map<Node*, int > ed_weight;
221
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){
225 Node *thisNode=*LI;
226 if(*thisNode == *getRoot()){
227 thisNode->setWeight(0);
228 parent[thisNode]=NULL;
229 ed_weight[thisNode]=0;
230 }
231 else{
232 thisNode->setWeight(inf);
233 }
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
237 }
238
239 //keep pulling out vertex of min wt from vt
240 while(!vt.empty()){
241 Node *u=*(min_element(vt.begin(), vt.end(), compare_nodes()));
242#ifdef DEBUG_PATH_PROFILES
Chris Lattner5328c6f2002-02-26 19:40:28 +0000243 cerr<<"popped wt"<<(u)->getWeight()<<"\n";
Anand Shuklad3d1fcd2002-02-26 18:58:39 +0000244 printNode(u);
245#endif
246 if(parent[u]!=NULL){ //so not root
247 Edge edge(parent[u],u, ed_weight[u]); //assign edge in spanning tree
248 st->addEdge(edge,ed_weight[u]);
249#ifdef DEBUG_PATH_PROFILES
250 cerr<<"added:\n";
251 printEdge(edge);
252#endif
253 }
254
255 //vt.erase(u);
256
257 //remove u frm vt
258 for(vector<Node *>::iterator VI=vt.begin(), VE=vt.end(); VI!=VE; ++VI){
259 if(**VI==*u){
260 vt.erase(VI);
261 break;
262 }
263 }
264
265 //assign wt(v) to all adjacent vertices v of u
266 //only if v is in vt
267 Graph::nodeList nl=getNodeList(u);
268 for(nodeList::iterator NI=nl.begin(), NE=nl.end(); NI!=NE; ++NI){
269 Node *v=NI->element;
270 int weight=-NI->weight;
271 //check if v is in vt
272 bool contains=false;
273 for(vector<Node *>::iterator VI=vt.begin(), VE=vt.end(); VI!=VE; ++VI){
274 if(**VI==*v){
275 contains=true;
276 break;
277 }
278 }
279#ifdef DEBUG_PATH_PROFILES
Chris Lattner5328c6f2002-02-26 19:40:28 +0000280 cerr<<"wt:v->wt"<<weight<<":"<<v->getWeight()<<"\n";
281 printNode(v);cerr<<"node wt:"<<(*v).weight<<"\n";
Anand Shuklad3d1fcd2002-02-26 18:58:39 +0000282#endif
283 //so if v in in vt, change wt(v) to wt(u->v)
284 //only if wt(u->v)<wt(v)
285 if(contains && weight<v->getWeight()){
286 parent[v]=u;
287 ed_weight[v]=weight;
288 v->setWeight(weight);
289#ifdef DEBUG_PATH_PROFILES
290 cerr<<v->getWeight()<<":Set weight------\n";
291 printGraph();
292 printEdge(Edge(u,v,weight));
293#endif
294 }
295 }
296 }
297 return st;
298}
299
300//print the graph (for debugging)
301void Graph::printGraph(){
302 list<Node *> lt=getAllNodes();
303 cerr<<"Graph---------------------\n";
304 for(list<Node *>::iterator LI=lt.begin(), LE=lt.end(); LI!=LE; ++LI){
305 cerr<<((*LI)->getElement())->getName()<<"->";
306 Graph::nodeList nl=getNodeList(*LI);
307 for(Graph::nodeList::iterator NI=nl.begin(), NE=nl.end(); NI!=NE; ++NI){
308 cerr<<":"<<"("<<(NI->element->getElement())
309 ->getName()<<":"<<NI->element->getWeight()<<","<<NI->weight<<")";
310 }
311 cerr<<"--------\n";
312 }
313}
314
315
316//get a list of nodes in the graph
317//in r-topological sorted order
318//note that we assumed graph to be connected
319list<Node *> Graph::reverseTopologicalSort() const{
320 list <Node *> toReturn;
321 list<Node *> lt=getAllNodes();
322 for(list<Node *>::iterator LI=lt.begin(), LE=lt.end(); LI!=LE; ++LI){
323 if((*LI)->getWeight()!=GREY && (*LI)->getWeight()!=BLACK)
324 DFS_Visit(*LI, toReturn);
325 }
326 return toReturn;
327}
328
329//a private method for doing DFS traversal of graph
330//this is used in determining the reverse topological sort
331//of the graph
332void Graph::DFS_Visit(Node *nd, list<Node *> &toReturn) const {
333 nd->setWeight(GREY);
334 list<Node *> lt=getSuccNodes(nd);
335 for(list<Node *>::iterator LI=lt.begin(), LE=lt.end(); LI!=LE; ++LI){
336 if((*LI)->getWeight()!=GREY && (*LI)->getWeight()!=BLACK)
337 DFS_Visit(*LI, toReturn);
338 }
339 toReturn.push_back(nd);
340}
341
342//Ordinarily, the graph is directional
343//this converts the graph into an
344//undirectional graph
345//This is done by adding an edge
346//v->u for all existing edges u->v
347void Graph::makeUnDirectional(){
348 list<Node* > allNodes=getAllNodes();
349 for(list<Node *>::iterator NI=allNodes.begin(), NE=allNodes.end(); NI!=NE;
350 ++NI) {
351 nodeList nl=getNodeList(*NI);
352 for(nodeList::iterator NLI=nl.begin(), NLE=nl.end(); NLI!=NLE; ++NLI){
353 Edge ed(NLI->element, *NI, NLI->weight);
354 if(!hasEdgeAndWt(ed)){
355#ifdef DEBUG_PATH_PROFILES
356 cerr<<"######doesn't hv\n";
357 printEdge(ed);
358#endif
359 addEdgeForce(ed);
360 }
361 }
362 }
363}
364
365//reverse the sign of weights on edges
366//this way, max-spanning tree could be obtained
367//usin min-spanning tree, and vice versa
368void Graph::reverseWts(){
369 list<Node *> allNodes=getAllNodes();
370 for(list<Node *>::iterator NI=allNodes.begin(), NE=allNodes.end(); NI!=NE;
371 ++NI) {
372 nodeList node_list=getNodeList(*NI);
373 for(nodeList::iterator NLI=nodes[*NI].begin(), NLE=nodes[*NI].end();
374 NLI!=NLE; ++NLI)
375 NLI->weight=-NLI->weight;
376 }
377}
378
379
380//getting the backedges in a graph
381//Its a variation of DFS to get the backedges in the graph
382//We get back edges by associating a time
383//and a color with each vertex.
384//The time of a vertex is the time when it was first visited
385//The color of a vertex is initially WHITE,
386//Changes to GREY when it is first visited,
387//and changes to BLACK when ALL its neighbors
388//have been visited
389//So we have a back edge when we meet a successor of
390//a node with smaller time, and GREY color
391void Graph::getBackEdges(vector<Edge > &be) const{
392 map<Node *, Color > color;
393 map<Node *, int > d;
394 list<Node *> allNodes=getAllNodes();
395 int time=0;
396 for(list<Node *>::const_iterator NI=allNodes.begin(), NE=allNodes.end();
397 NI!=NE; ++NI){
398 if(color[*NI]!=GREY && color[*NI]!=BLACK)
399 getBackEdgesVisit(*NI, be, color, d, time);
400 }
401}
402
403//helper function to get back edges: it is called by
404//the "getBackEdges" function above
405void Graph::getBackEdgesVisit(Node *u, vector<Edge > &be,
406 map<Node *, Color > &color,
407 map<Node *, int > &d, int &time) const{
408 color[u]=GREY;
409 time++;
410 d[u]=time;
411 list<Node *> succ_list=getSuccNodes(u);
412
413 for(list<Node *>::const_iterator v=succ_list.begin(), ve=succ_list.end();
414 v!=ve; ++v){
415 if(color[*v]!=GREY && color[*v]!=BLACK){
416 getBackEdgesVisit(*v, be, color, d, time);
417 }
418
419 //now checking for d and f vals
420 if(color[*v]==GREY){
421 //so v is ancestor of u if time of u > time of v
422 if(d[u] >= d[*v]){
423 Edge *ed=new Edge(u, *v);
424 if (!(*u == *getExit() && **v == *getRoot()))
425 be.push_back(*ed); // choose the forward edges
426 }
427 }
428 }
429 color[u]=BLACK;//done with visiting the node and its neighbors
430}
431
432