1 //===- GraphAuxiliary.cpp - Auxiliary functions on graph ------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file was developed by the LLVM research group and is distributed under
6 // the University of Illinois Open Source License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // auxiliary function associated with graph: they all operate on graph, and help
11 // in inserting instrumentation for trace generation
13 //===----------------------------------------------------------------------===//
15 #include "llvm/Pass.h"
16 #include "llvm/Module.h"
17 #include "llvm/iTerminators.h"
18 #include "Support/Debug.h"
27 //check if 2 edges are equal (same endpoints and same weight)
28 static bool edgesEqual(Edge ed1, Edge ed2){
29 return ((ed1==ed2) && ed1.getWeight()==ed2.getWeight());
32 //Get the vector of edges that are to be instrumented in the graph
33 static void getChords(vector<Edge > &chords, Graph &g, Graph st){
34 //make sure the spanning tree is directional
35 //iterate over ALL the edges of the graph
36 vector<Node *> allNodes=g.getAllNodes();
37 for(vector<Node *>::iterator NI=allNodes.begin(), NE=allNodes.end(); NI!=NE;
39 Graph::nodeList node_list=g.getNodeList(*NI);
40 for(Graph::nodeList::iterator NLI=node_list.begin(), NLE=node_list.end();
42 Edge f(*NI, NLI->element,NLI->weight, NLI->randId);
43 if(!(st.hasEdgeAndWt(f)))//addnl
49 //Given a tree t, and a "directed graph" g
50 //replace the edges in the tree t with edges that exist in graph
51 //The tree is formed from "undirectional" copy of graph
52 //So whatever edges the tree has, the undirectional graph
53 //would have too. This function corrects some of the directions in
54 //the tree so that now, all edge directions in the tree match
55 //the edge directions of corresponding edges in the directed graph
56 static void removeTreeEdges(Graph &g, Graph& t){
57 vector<Node* > allNodes=t.getAllNodes();
58 for(vector<Node *>::iterator NI=allNodes.begin(), NE=allNodes.end(); NI!=NE;
60 Graph::nodeList nl=t.getNodeList(*NI);
61 for(Graph::nodeList::iterator NLI=nl.begin(), NLE=nl.end(); NLI!=NLE;++NLI){
62 Edge ed(NLI->element, *NI, NLI->weight);
63 if(!g.hasEdgeAndWt(ed)) t.removeEdge(ed);//tree has only one edge
64 //between any pair of vertices, so no need to delete by edge wt
69 //Assign a value to all the edges in the graph
70 //such that if we traverse along any path from root to exit, and
71 //add up the edge values, we get a path number that uniquely
72 //refers to the path we travelled
73 int valueAssignmentToEdges(Graph& g, map<Node *, int> nodePriority,
75 vector<Node *> revtop=g.reverseTopologicalSort();
76 map<Node *,int > NumPaths;
77 for(vector<Node *>::iterator RI=revtop.begin(), RE=revtop.end();
84 // Modified Graph::nodeList &nlist=g.getNodeList(*RI);
85 Graph::nodeList &nlist=g.getSortedNodeList(*RI, be);
87 //sort nodelist by increasing order of numpaths
91 for(int i=0;i<sz-1; i++){
93 for(int j=i+1; j<sz; j++){
94 BasicBlock *bb1 = nlist[j].element->getElement();
95 BasicBlock *bb2 = nlist[min].element->getElement();
97 if(bb1 == bb2) continue;
99 if(*RI == g.getRoot()){
100 assert(nodePriority[nlist[min].element]!=
101 nodePriority[nlist[j].element]
102 && "priorities can't be same!");
104 if(nodePriority[nlist[j].element] <
105 nodePriority[nlist[min].element])
110 TerminatorInst *tti = (*RI)->getElement()->getTerminator();
112 BranchInst *ti = cast<BranchInst>(tti);
113 assert(ti && "not a branch");
114 assert(ti->getNumSuccessors()==2 && "less successors!");
116 BasicBlock *tB = ti->getSuccessor(0);
117 BasicBlock *fB = ti->getSuccessor(1);
119 if(tB == bb1 || fB == bb2)
124 graphListElement tempEl=nlist[min];
130 for(Graph::nodeList::iterator GLI=nlist.begin(), GLE=nlist.end();
132 GLI->weight=NumPaths[*RI];
133 NumPaths[*RI]+=NumPaths[GLI->element];
137 return NumPaths[g.getRoot()];
140 //This is a helper function to get the edge increments
141 //This is used in conjunction with inc_DFS
142 //to get the edge increments
143 //Edge increment implies assigning a value to all the edges in the graph
144 //such that if we traverse along any path from root to exit, and
145 //add up the edge values, we get a path number that uniquely
146 //refers to the path we travelled
147 //inc_Dir tells whether 2 edges are in same, or in different directions
148 //if same direction, return 1, else -1
149 static int inc_Dir(Edge e, Edge f){
153 //check that the edges must have at least one common endpoint
154 assert(*(e.getFirst())==*(f.getFirst()) ||
155 *(e.getFirst())==*(f.getSecond()) ||
156 *(e.getSecond())==*(f.getFirst()) ||
157 *(e.getSecond())==*(f.getSecond()));
159 if(*(e.getFirst())==*(f.getSecond()) ||
160 *(e.getSecond())==*(f.getFirst()))
167 //used for getting edge increments (read comments above in inc_Dir)
168 //inc_DFS is a modification of DFS
169 static void inc_DFS(Graph& g,Graph& t,map<Edge, int, EdgeCompare2>& Increment,
170 int events, Node *v, Edge e){
172 vector<Node *> allNodes=t.getAllNodes();
174 for(vector<Node *>::iterator NI=allNodes.begin(), NE=allNodes.end(); NI!=NE;
176 Graph::nodeList node_list=t.getNodeList(*NI);
177 for(Graph::nodeList::iterator NLI=node_list.begin(), NLE=node_list.end();
179 Edge f(*NI, NLI->element,NLI->weight, NLI->randId);
180 if(!edgesEqual(f,e) && *v==*(f.getSecond())){
181 int dir_count=inc_Dir(e,f);
182 int wt=1*f.getWeight();
183 inc_DFS(g,t, Increment, dir_count*events+wt, f.getFirst(), f);
188 for(vector<Node *>::iterator NI=allNodes.begin(), NE=allNodes.end(); NI!=NE;
190 Graph::nodeList node_list=t.getNodeList(*NI);
191 for(Graph::nodeList::iterator NLI=node_list.begin(), NLE=node_list.end();
193 Edge f(*NI, NLI->element,NLI->weight, NLI->randId);
194 if(!edgesEqual(f,e) && *v==*(f.getFirst())){
195 int dir_count=inc_Dir(e,f);
196 int wt=f.getWeight();
197 inc_DFS(g,t, Increment, dir_count*events+wt,
203 allNodes=g.getAllNodes();
204 for(vector<Node *>::iterator NI=allNodes.begin(), NE=allNodes.end(); NI!=NE;
206 Graph::nodeList node_list=g.getNodeList(*NI);
207 for(Graph::nodeList::iterator NLI=node_list.begin(), NLE=node_list.end();
209 Edge f(*NI, NLI->element,NLI->weight, NLI->randId);
210 if(!(t.hasEdgeAndWt(f)) && (*v==*(f.getSecond()) ||
211 *v==*(f.getFirst()))){
212 int dir_count=inc_Dir(e,f);
213 Increment[f]+=dir_count*events;
219 //Now we select a subset of all edges
220 //and assign them some values such that
221 //if we consider just this subset, it still represents
222 //the path sum along any path in the graph
223 static map<Edge, int, EdgeCompare2> getEdgeIncrements(Graph& g, Graph& t,
225 //get all edges in g-t
226 map<Edge, int, EdgeCompare2> Increment;
228 vector<Node *> allNodes=g.getAllNodes();
230 for(vector<Node *>::iterator NI=allNodes.begin(), NE=allNodes.end(); NI!=NE;
232 Graph::nodeList node_list=g.getSortedNodeList(*NI, be);
233 //modified g.getNodeList(*NI);
234 for(Graph::nodeList::iterator NLI=node_list.begin(), NLE=node_list.end();
236 Edge ed(*NI, NLI->element,NLI->weight,NLI->randId);
237 if(!(t.hasEdgeAndWt(ed))){
244 inc_DFS(g,t,Increment, 0, g.getRoot(), *ed);
246 for(vector<Node *>::iterator NI=allNodes.begin(), NE=allNodes.end(); NI!=NE;
248 Graph::nodeList node_list=g.getSortedNodeList(*NI, be);
249 //modified g.getNodeList(*NI);
250 for(Graph::nodeList::iterator NLI=node_list.begin(), NLE=node_list.end();
252 Edge ed(*NI, NLI->element,NLI->weight, NLI->randId);
253 if(!(t.hasEdgeAndWt(ed))){
254 int wt=ed.getWeight();
264 const graphListElement *findNodeInList(const Graph::nodeList &NL,
267 graphListElement *findNodeInList(Graph::nodeList &NL, Node *N);
270 //Based on edgeIncrements (above), now obtain
271 //the kind of code to be inserted along an edge
272 //The idea here is to minimize the computation
273 //by inserting only the needed code
274 static void getCodeInsertions(Graph &g, map<Edge, getEdgeCode *, EdgeCompare2> &instr,
275 vector<Edge > &chords,
276 map<Edge,int, EdgeCompare2> &edIncrements){
278 //Register initialization code
280 ws.push_back(g.getRoot());
285 Graph::nodeList succs=g.getNodeList(v);
287 for(Graph::nodeList::iterator nl=succs.begin(), ne=succs.end();
289 int edgeWt=nl->weight;
292 Edge ed(v,w, edgeWt, nl->randId);
294 for(vector<Edge>::iterator CI=chords.begin(), CE=chords.end();
295 CI!=CE && !hasEdge;++CI){
296 if(*CI==ed && CI->getWeight()==edgeWt){//modf
301 if(hasEdge){//so its a chord edge
302 getEdgeCode *edCd=new getEdgeCode();
304 edCd->setInc(edIncrements[ed]);
307 else if(g.getNumberOfIncomingEdges(w)==1){
311 getEdgeCode *edCd=new getEdgeCode();
319 /////Memory increment code
320 ws.push_back(g.getExit());
329 vector<Node *> lllt=g.getAllNodes();
330 for(vector<Node *>::iterator EII=lllt.begin(); EII!=lllt.end() ;++EII){
332 Graph::nodeList &nl = g.getNodeList(lnode);
333 //graphListElement *N = findNodeInList(nl, w);
334 for(Graph::nodeList::const_iterator N = nl.begin(),
335 NNEN = nl.end(); N!= NNEN; ++N){
336 if (*N->element == *w){
340 Edge ed(v,w, N->weight, N->randId);
341 getEdgeCode *edCd=new getEdgeCode();
343 for(vector<Edge>::iterator CI=chords.begin(), CE=chords.end(); CI!=CE;
345 if(*CI==ed && CI->getWeight()==N->weight){
352 if(instr[ed]!=NULL && instr[ed]->getCond()==1){
353 instr[ed]->setCond(4);
357 edCd->setInc(edIncrements[ed]);
362 else if(g.getNumberOfOutgoingEdges(v)==1)
372 ///// Register increment code
373 for(vector<Edge>::iterator CI=chords.begin(), CE=chords.end(); CI!=CE; ++CI){
374 getEdgeCode *edCd=new getEdgeCode();
375 if(instr[*CI]==NULL){
377 edCd->setInc(edIncrements[*CI]);
383 //Add dummy edges corresponding to the back edges
384 //If a->b is a backedge
385 //then incoming dummy edge is root->b
386 //and outgoing dummy edge is a->exit
388 void addDummyEdges(vector<Edge > &stDummy,
389 vector<Edge > &exDummy,
390 Graph &g, vector<Edge> &be){
391 for(vector<Edge >::iterator VI=be.begin(), VE=be.end(); VI!=VE; ++VI){
393 Node *first=ed.getFirst();
394 Node *second=ed.getSecond();
397 if(!(*second==*(g.getRoot()))){
398 Edge *st=new Edge(g.getRoot(), second, ed.getWeight(), ed.getRandId());
399 stDummy.push_back(*st);
403 if(!(*first==*(g.getExit()))){
404 Edge *ex=new Edge(first, g.getExit(), ed.getWeight(), ed.getRandId());
405 exDummy.push_back(*ex);
411 //print a given edge in the form BB1Label->BB2Label
412 void printEdge(Edge ed){
413 cerr<<((ed.getFirst())->getElement())
414 ->getName()<<"->"<<((ed.getSecond())
415 ->getElement())->getName()<<
416 ":"<<ed.getWeight()<<" rndId::"<<ed.getRandId()<<"\n";
419 //Move the incoming dummy edge code and outgoing dummy
420 //edge code over to the corresponding back edge
421 static void moveDummyCode(vector<Edge> &stDummy,
422 vector<Edge> &exDummy,
424 map<Edge, getEdgeCode *, EdgeCompare2> &insertions,
426 typedef vector<Edge >::iterator vec_iter;
428 map<Edge,getEdgeCode *, EdgeCompare2> temp;
429 //iterate over edges with code
430 std::vector<Edge> toErase;
431 for(map<Edge,getEdgeCode *, EdgeCompare2>::iterator MI=insertions.begin(),
432 ME=insertions.end(); MI!=ME; ++MI){
434 getEdgeCode *edCd=MI->second;
437 //iterate over be, and check if its starts and end vertices hv code
438 for(vector<Edge>::iterator BEI=be.begin(), BEE=be.end(); BEI!=BEE; ++BEI){
439 if(ed.getRandId()==BEI->getRandId()){
442 temp[*BEI]=new getEdgeCode();
444 //so ed is either in st, or ex!
445 if(ed.getFirst()==g.getRoot()){
448 temp[*BEI]->setCdIn(edCd);
449 toErase.push_back(ed);
451 else if(ed.getSecond()==g.getExit()){
454 toErase.push_back(ed);
455 temp[*BEI]->setCdOut(edCd);
458 assert(false && "Not found in either start or end! Rand failed?");
464 for(vector<Edge >::iterator vmi=toErase.begin(), vme=toErase.end(); vmi!=vme;
466 insertions.erase(*vmi);
467 g.removeEdgeWithWt(*vmi);
470 for(map<Edge,getEdgeCode *, EdgeCompare2>::iterator MI=temp.begin(),
471 ME=temp.end(); MI!=ME; ++MI){
472 insertions[MI->first]=MI->second;
475 #ifdef DEBUG_PATH_PROFILES
476 cerr<<"size of deletions: "<<toErase.size()<<"\n";
477 cerr<<"SIZE OF INSERTIONS AFTER DEL "<<insertions.size()<<"\n";
482 //Do graph processing: to determine minimal edge increments,
483 //appropriate code insertions etc and insert the code at
484 //appropriate locations
485 void processGraph(Graph &g,
489 vector<Edge >& stDummy,
490 vector<Edge >& exDummy,
491 int numPaths, int MethNo,
494 //Given a graph: with exit->root edge, do the following in seq:
496 //2. insert dummy edges and remove back edges
497 //3. get edge assignments
498 //4. Get Max spanning tree of graph:
499 // -Make graph g2=g undirectional
500 // -Get Max spanning tree t
501 // -Make t undirectional
502 // -remove edges from t not in graph g
503 //5. Get edge increments
504 //6. Get code insertions
505 //7. move code on dummy edges over to the back edges
508 //This is used as maximum "weight" for
510 //This would hold all
511 //right as long as number of paths in the graph
513 const int Infinity=99999999;
516 //step 1-3 are already done on the graph when this function is called
517 DEBUG(printGraph(g));
519 //step 4: Get Max spanning tree of graph
521 //now insert exit to root edge
522 //if its there earlier, remove it!
523 //assign it weight Infinity
524 //so that this edge IS ALWAYS IN spanning tree
525 //Note than edges in spanning tree do not get
526 //instrumented: and we do not want the
527 //edge exit->root to get instrumented
528 //as it MAY BE a dummy edge
529 Edge ed(g.getExit(),g.getRoot(),Infinity);
530 g.addEdge(ed,Infinity);
533 //make g2 undirectional: this gives a better
534 //maximal spanning tree
535 g2.makeUnDirectional();
536 DEBUG(printGraph(g2));
538 Graph *t=g2.getMaxSpanningTree();
539 #ifdef DEBUG_PATH_PROFILES
540 std::cerr<<"Original maxspanning tree\n";
543 //now edges of tree t have weights reversed
544 //(negative) because the algorithm used
545 //to find max spanning tree is
546 //actually for finding min spanning tree
547 //so get back the original weights
550 //Ordinarily, the graph is directional
551 //lets converts the graph into an
552 //undirectional graph
553 //This is done by adding an edge
554 //v->u for all existing edges u->v
555 t->makeUnDirectional();
557 //Given a tree t, and a "directed graph" g
558 //replace the edges in the tree t with edges that exist in graph
559 //The tree is formed from "undirectional" copy of graph
560 //So whatever edges the tree has, the undirectional graph
561 //would have too. This function corrects some of the directions in
562 //the tree so that now, all edge directions in the tree match
563 //the edge directions of corresponding edges in the directed graph
564 removeTreeEdges(g, *t);
566 #ifdef DEBUG_PATH_PROFILES
567 cerr<<"Final Spanning tree---------\n";
569 cerr<<"-------end spanning tree\n";
572 //now remove the exit->root node
573 //and re-add it with weight 0
574 //since infinite weight is kinda confusing
576 Edge edNew(g.getExit(), g.getRoot(),0);
586 //step 5: Get edge increments
588 //Now we select a subset of all edges
589 //and assign them some values such that
590 //if we consider just this subset, it still represents
591 //the path sum along any path in the graph
593 map<Edge, int, EdgeCompare2> increment=getEdgeIncrements(g,*t, be);
594 #ifdef DEBUG_PATH_PROFILES
595 //print edge increments for debugging
596 std::cerr<<"Edge Increments------\n";
597 for(map<Edge, int, EdgeCompare2>::iterator MMI=increment.begin(), MME=increment.end(); MMI != MME; ++MMI){
598 printEdge(MMI->first);
599 std::cerr<<"Increment for above:"<<MMI->second<<"\n";
601 std::cerr<<"-------end of edge increments\n";
605 //step 6: Get code insertions
607 //Based on edgeIncrements (above), now obtain
608 //the kind of code to be inserted along an edge
609 //The idea here is to minimize the computation
610 //by inserting only the needed code
612 getChords(chords, g, *t);
615 map<Edge, getEdgeCode *, EdgeCompare2> codeInsertions;
616 getCodeInsertions(g, codeInsertions, chords,increment);
618 #ifdef DEBUG_PATH_PROFILES
619 //print edges with code for debugging
620 cerr<<"Code inserted in following---------------\n";
621 for(map<Edge, getEdgeCode *, EdgeCompare2>::iterator cd_i=codeInsertions.begin(),
622 cd_e=codeInsertions.end(); cd_i!=cd_e; ++cd_i){
623 printEdge(cd_i->first);
624 cerr<<cd_i->second->getCond()<<":"<<cd_i->second->getInc()<<"\n";
626 cerr<<"-----end insertions\n";
629 //step 7: move code on dummy edges over to the back edges
631 //Move the incoming dummy edge code and outgoing dummy
632 //edge code over to the corresponding back edge
634 moveDummyCode(stDummy, exDummy, be, codeInsertions, g);
636 #ifdef DEBUG_PATH_PROFILES
638 cerr<<"After moving dummy code\n";
639 for(map<Edge, getEdgeCode *>::iterator cd_i=codeInsertions.begin(),
640 cd_e=codeInsertions.end(); cd_i != cd_e; ++cd_i){
641 printEdge(cd_i->first);
642 cerr<<cd_i->second->getCond()<<":"
643 <<cd_i->second->getInc()<<"\n";
645 cerr<<"Dummy end------------\n";
649 //see what it looks like...
650 //now insert code along edges which have codes on them
651 for(map<Edge, getEdgeCode *>::iterator MI=codeInsertions.begin(),
652 ME=codeInsertions.end(); MI!=ME; ++MI){
654 insertBB(ed, MI->second, rInst, countInst, numPaths, MethNo, threshold);
658 //print the graph (for debugging)
659 void printGraph(Graph &g){
660 vector<Node *> lt=g.getAllNodes();
661 cerr<<"Graph---------------------\n";
662 for(vector<Node *>::iterator LI=lt.begin();
664 cerr<<((*LI)->getElement())->getName()<<"->";
665 Graph::nodeList nl=g.getNodeList(*LI);
666 for(Graph::nodeList::iterator NI=nl.begin();
668 cerr<<":"<<"("<<(NI->element->getElement())
669 ->getName()<<":"<<NI->element->getWeight()<<","<<NI->weight<<","
674 cerr<<"--------------------Graph\n";