1 //===-- GrapAuxiliary.cpp- Auxiliary functions on graph ----------*- C++ -*--=//
3 //auxiliary function associated with graph: they
4 //all operate on graph, and help in inserting
5 //instrumentation for trace generation
7 //===----------------------------------------------------------------------===//
10 #include "llvm/Module.h"
11 #include "llvm/iTerminators.h"
12 #include "Support/Debug.h"
21 //check if 2 edges are equal (same endpoints and same weight)
22 static bool edgesEqual(Edge ed1, Edge ed2){
23 return ((ed1==ed2) && ed1.getWeight()==ed2.getWeight());
26 //Get the vector of edges that are to be instrumented in the graph
27 static void getChords(vector<Edge > &chords, Graph &g, Graph st){
28 //make sure the spanning tree is directional
29 //iterate over ALL the edges of the graph
30 vector<Node *> allNodes=g.getAllNodes();
31 for(vector<Node *>::iterator NI=allNodes.begin(), NE=allNodes.end(); NI!=NE;
33 Graph::nodeList node_list=g.getNodeList(*NI);
34 for(Graph::nodeList::iterator NLI=node_list.begin(), NLE=node_list.end();
36 Edge f(*NI, NLI->element,NLI->weight, NLI->randId);
37 if(!(st.hasEdgeAndWt(f)))//addnl
43 //Given a tree t, and a "directed graph" g
44 //replace the edges in the tree t with edges that exist in graph
45 //The tree is formed from "undirectional" copy of graph
46 //So whatever edges the tree has, the undirectional graph
47 //would have too. This function corrects some of the directions in
48 //the tree so that now, all edge directions in the tree match
49 //the edge directions of corresponding edges in the directed graph
50 static void removeTreeEdges(Graph &g, Graph& t){
51 vector<Node* > allNodes=t.getAllNodes();
52 for(vector<Node *>::iterator NI=allNodes.begin(), NE=allNodes.end(); NI!=NE;
54 Graph::nodeList nl=t.getNodeList(*NI);
55 for(Graph::nodeList::iterator NLI=nl.begin(), NLE=nl.end(); NLI!=NLE;++NLI){
56 Edge ed(NLI->element, *NI, NLI->weight);
57 if(!g.hasEdgeAndWt(ed)) t.removeEdge(ed);//tree has only one edge
58 //between any pair of vertices, so no need to delete by edge wt
63 //Assign a value to all the edges in the graph
64 //such that if we traverse along any path from root to exit, and
65 //add up the edge values, we get a path number that uniquely
66 //refers to the path we travelled
67 int valueAssignmentToEdges(Graph& g, map<Node *, int> nodePriority,
69 vector<Node *> revtop=g.reverseTopologicalSort();
70 map<Node *,int > NumPaths;
71 for(vector<Node *>::iterator RI=revtop.begin(), RE=revtop.end();
78 // Modified Graph::nodeList &nlist=g.getNodeList(*RI);
79 Graph::nodeList &nlist=g.getSortedNodeList(*RI, be);
81 //sort nodelist by increasing order of numpaths
85 for(int i=0;i<sz-1; i++){
87 for(int j=i+1; j<sz; j++){
88 BasicBlock *bb1 = nlist[j].element->getElement();
89 BasicBlock *bb2 = nlist[min].element->getElement();
91 if(bb1 == bb2) continue;
93 if(*RI == g.getRoot()){
94 assert(nodePriority[nlist[min].element]!=
95 nodePriority[nlist[j].element]
96 && "priorities can't be same!");
98 if(nodePriority[nlist[j].element] <
99 nodePriority[nlist[min].element])
104 TerminatorInst *tti = (*RI)->getElement()->getTerminator();
106 BranchInst *ti = cast<BranchInst>(tti);
107 assert(ti && "not a branch");
108 assert(ti->getNumSuccessors()==2 && "less successors!");
110 BasicBlock *tB = ti->getSuccessor(0);
111 BasicBlock *fB = ti->getSuccessor(1);
113 if(tB == bb1 || fB == bb2)
118 graphListElement tempEl=nlist[min];
124 for(Graph::nodeList::iterator GLI=nlist.begin(), GLE=nlist.end();
126 GLI->weight=NumPaths[*RI];
127 NumPaths[*RI]+=NumPaths[GLI->element];
131 return NumPaths[g.getRoot()];
134 //This is a helper function to get the edge increments
135 //This is used in conjunction with inc_DFS
136 //to get the edge increments
137 //Edge increment implies assigning a value to all the edges in the graph
138 //such that if we traverse along any path from root to exit, and
139 //add up the edge values, we get a path number that uniquely
140 //refers to the path we travelled
141 //inc_Dir tells whether 2 edges are in same, or in different directions
142 //if same direction, return 1, else -1
143 static int inc_Dir(Edge e, Edge f){
147 //check that the edges must have at least one common endpoint
148 assert(*(e.getFirst())==*(f.getFirst()) ||
149 *(e.getFirst())==*(f.getSecond()) ||
150 *(e.getSecond())==*(f.getFirst()) ||
151 *(e.getSecond())==*(f.getSecond()));
153 if(*(e.getFirst())==*(f.getSecond()) ||
154 *(e.getSecond())==*(f.getFirst()))
161 //used for getting edge increments (read comments above in inc_Dir)
162 //inc_DFS is a modification of DFS
163 static void inc_DFS(Graph& g,Graph& t,map<Edge, int, EdgeCompare2>& Increment,
164 int events, Node *v, Edge e){
166 vector<Node *> allNodes=t.getAllNodes();
168 for(vector<Node *>::iterator NI=allNodes.begin(), NE=allNodes.end(); NI!=NE;
170 Graph::nodeList node_list=t.getNodeList(*NI);
171 for(Graph::nodeList::iterator NLI=node_list.begin(), NLE=node_list.end();
173 Edge f(*NI, NLI->element,NLI->weight, NLI->randId);
174 if(!edgesEqual(f,e) && *v==*(f.getSecond())){
175 int dir_count=inc_Dir(e,f);
176 int wt=1*f.getWeight();
177 inc_DFS(g,t, Increment, dir_count*events+wt, f.getFirst(), f);
182 for(vector<Node *>::iterator NI=allNodes.begin(), NE=allNodes.end(); NI!=NE;
184 Graph::nodeList node_list=t.getNodeList(*NI);
185 for(Graph::nodeList::iterator NLI=node_list.begin(), NLE=node_list.end();
187 Edge f(*NI, NLI->element,NLI->weight, NLI->randId);
188 if(!edgesEqual(f,e) && *v==*(f.getFirst())){
189 int dir_count=inc_Dir(e,f);
190 int wt=f.getWeight();
191 inc_DFS(g,t, Increment, dir_count*events+wt,
197 allNodes=g.getAllNodes();
198 for(vector<Node *>::iterator NI=allNodes.begin(), NE=allNodes.end(); NI!=NE;
200 Graph::nodeList node_list=g.getNodeList(*NI);
201 for(Graph::nodeList::iterator NLI=node_list.begin(), NLE=node_list.end();
203 Edge f(*NI, NLI->element,NLI->weight, NLI->randId);
204 if(!(t.hasEdgeAndWt(f)) && (*v==*(f.getSecond()) ||
205 *v==*(f.getFirst()))){
206 int dir_count=inc_Dir(e,f);
207 Increment[f]+=dir_count*events;
213 //Now we select a subset of all edges
214 //and assign them some values such that
215 //if we consider just this subset, it still represents
216 //the path sum along any path in the graph
217 static map<Edge, int, EdgeCompare2> getEdgeIncrements(Graph& g, Graph& t,
219 //get all edges in g-t
220 map<Edge, int, EdgeCompare2> Increment;
222 vector<Node *> allNodes=g.getAllNodes();
224 for(vector<Node *>::iterator NI=allNodes.begin(), NE=allNodes.end(); NI!=NE;
226 Graph::nodeList node_list=g.getSortedNodeList(*NI, be);
227 //modified g.getNodeList(*NI);
228 for(Graph::nodeList::iterator NLI=node_list.begin(), NLE=node_list.end();
230 Edge ed(*NI, NLI->element,NLI->weight,NLI->randId);
231 if(!(t.hasEdgeAndWt(ed))){
238 inc_DFS(g,t,Increment, 0, g.getRoot(), *ed);
240 for(vector<Node *>::iterator NI=allNodes.begin(), NE=allNodes.end(); NI!=NE;
242 Graph::nodeList node_list=g.getSortedNodeList(*NI, be);
243 //modified g.getNodeList(*NI);
244 for(Graph::nodeList::iterator NLI=node_list.begin(), NLE=node_list.end();
246 Edge ed(*NI, NLI->element,NLI->weight, NLI->randId);
247 if(!(t.hasEdgeAndWt(ed))){
248 int wt=ed.getWeight();
258 const graphListElement *findNodeInList(const Graph::nodeList &NL,
261 graphListElement *findNodeInList(Graph::nodeList &NL, Node *N);
264 //Based on edgeIncrements (above), now obtain
265 //the kind of code to be inserted along an edge
266 //The idea here is to minimize the computation
267 //by inserting only the needed code
268 static void getCodeInsertions(Graph &g, map<Edge, getEdgeCode *, EdgeCompare2> &instr,
269 vector<Edge > &chords,
270 map<Edge,int, EdgeCompare2> &edIncrements){
272 //Register initialization code
274 ws.push_back(g.getRoot());
279 Graph::nodeList succs=g.getNodeList(v);
281 for(Graph::nodeList::iterator nl=succs.begin(), ne=succs.end();
283 int edgeWt=nl->weight;
286 Edge ed(v,w, edgeWt, nl->randId);
288 for(vector<Edge>::iterator CI=chords.begin(), CE=chords.end();
289 CI!=CE && !hasEdge;++CI){
290 if(*CI==ed && CI->getWeight()==edgeWt){//modf
295 if(hasEdge){//so its a chord edge
296 getEdgeCode *edCd=new getEdgeCode();
298 edCd->setInc(edIncrements[ed]);
301 else if(g.getNumberOfIncomingEdges(w)==1){
305 getEdgeCode *edCd=new getEdgeCode();
313 /////Memory increment code
314 ws.push_back(g.getExit());
323 vector<Node *> lllt=g.getAllNodes();
324 for(vector<Node *>::iterator EII=lllt.begin(); EII!=lllt.end() ;++EII){
326 Graph::nodeList &nl = g.getNodeList(lnode);
327 //graphListElement *N = findNodeInList(nl, w);
328 for(Graph::nodeList::const_iterator N = nl.begin(),
329 NNEN = nl.end(); N!= NNEN; ++N){
330 if (*N->element == *w){
334 Edge ed(v,w, N->weight, N->randId);
335 getEdgeCode *edCd=new getEdgeCode();
337 for(vector<Edge>::iterator CI=chords.begin(), CE=chords.end(); CI!=CE;
339 if(*CI==ed && CI->getWeight()==N->weight){
346 if(instr[ed]!=NULL && instr[ed]->getCond()==1){
347 instr[ed]->setCond(4);
351 edCd->setInc(edIncrements[ed]);
356 else if(g.getNumberOfOutgoingEdges(v)==1)
366 ///// Register increment code
367 for(vector<Edge>::iterator CI=chords.begin(), CE=chords.end(); CI!=CE; ++CI){
368 getEdgeCode *edCd=new getEdgeCode();
369 if(instr[*CI]==NULL){
371 edCd->setInc(edIncrements[*CI]);
377 //Add dummy edges corresponding to the back edges
378 //If a->b is a backedge
379 //then incoming dummy edge is root->b
380 //and outgoing dummy edge is a->exit
382 void addDummyEdges(vector<Edge > &stDummy,
383 vector<Edge > &exDummy,
384 Graph &g, vector<Edge> &be){
385 for(vector<Edge >::iterator VI=be.begin(), VE=be.end(); VI!=VE; ++VI){
387 Node *first=ed.getFirst();
388 Node *second=ed.getSecond();
391 if(!(*second==*(g.getRoot()))){
392 Edge *st=new Edge(g.getRoot(), second, ed.getWeight(), ed.getRandId());
393 stDummy.push_back(*st);
397 if(!(*first==*(g.getExit()))){
398 Edge *ex=new Edge(first, g.getExit(), ed.getWeight(), ed.getRandId());
399 exDummy.push_back(*ex);
405 //print a given edge in the form BB1Label->BB2Label
406 void printEdge(Edge ed){
407 cerr<<((ed.getFirst())->getElement())
408 ->getName()<<"->"<<((ed.getSecond())
409 ->getElement())->getName()<<
410 ":"<<ed.getWeight()<<" rndId::"<<ed.getRandId()<<"\n";
413 //Move the incoming dummy edge code and outgoing dummy
414 //edge code over to the corresponding back edge
415 static void moveDummyCode(vector<Edge> &stDummy,
416 vector<Edge> &exDummy,
418 map<Edge, getEdgeCode *, EdgeCompare2> &insertions,
420 typedef vector<Edge >::iterator vec_iter;
422 map<Edge,getEdgeCode *, EdgeCompare2> temp;
423 //iterate over edges with code
424 std::vector<Edge> toErase;
425 for(map<Edge,getEdgeCode *, EdgeCompare2>::iterator MI=insertions.begin(),
426 ME=insertions.end(); MI!=ME; ++MI){
428 getEdgeCode *edCd=MI->second;
431 //iterate over be, and check if its starts and end vertices hv code
432 for(vector<Edge>::iterator BEI=be.begin(), BEE=be.end(); BEI!=BEE; ++BEI){
433 if(ed.getRandId()==BEI->getRandId()){
436 temp[*BEI]=new getEdgeCode();
438 //so ed is either in st, or ex!
439 if(ed.getFirst()==g.getRoot()){
442 temp[*BEI]->setCdIn(edCd);
443 toErase.push_back(ed);
445 else if(ed.getSecond()==g.getExit()){
448 toErase.push_back(ed);
449 temp[*BEI]->setCdOut(edCd);
452 assert(false && "Not found in either start or end! Rand failed?");
458 for(vector<Edge >::iterator vmi=toErase.begin(), vme=toErase.end(); vmi!=vme;
460 insertions.erase(*vmi);
461 g.removeEdgeWithWt(*vmi);
464 for(map<Edge,getEdgeCode *, EdgeCompare2>::iterator MI=temp.begin(),
465 ME=temp.end(); MI!=ME; ++MI){
466 insertions[MI->first]=MI->second;
469 #ifdef DEBUG_PATH_PROFILES
470 cerr<<"size of deletions: "<<toErase.size()<<"\n";
471 cerr<<"SIZE OF INSERTIONS AFTER DEL "<<insertions.size()<<"\n";
476 //Do graph processing: to determine minimal edge increments,
477 //appropriate code insertions etc and insert the code at
478 //appropriate locations
479 void processGraph(Graph &g,
483 vector<Edge >& stDummy,
484 vector<Edge >& exDummy,
485 int numPaths, int MethNo,
488 //Given a graph: with exit->root edge, do the following in seq:
490 //2. insert dummy edges and remove back edges
491 //3. get edge assignments
492 //4. Get Max spanning tree of graph:
493 // -Make graph g2=g undirectional
494 // -Get Max spanning tree t
495 // -Make t undirectional
496 // -remove edges from t not in graph g
497 //5. Get edge increments
498 //6. Get code insertions
499 //7. move code on dummy edges over to the back edges
502 //This is used as maximum "weight" for
504 //This would hold all
505 //right as long as number of paths in the graph
507 const int Infinity=99999999;
510 //step 1-3 are already done on the graph when this function is called
511 DEBUG(printGraph(g));
513 //step 4: Get Max spanning tree of graph
515 //now insert exit to root edge
516 //if its there earlier, remove it!
517 //assign it weight Infinity
518 //so that this edge IS ALWAYS IN spanning tree
519 //Note than edges in spanning tree do not get
520 //instrumented: and we do not want the
521 //edge exit->root to get instrumented
522 //as it MAY BE a dummy edge
523 Edge ed(g.getExit(),g.getRoot(),Infinity);
524 g.addEdge(ed,Infinity);
527 //make g2 undirectional: this gives a better
528 //maximal spanning tree
529 g2.makeUnDirectional();
530 DEBUG(printGraph(g2));
532 Graph *t=g2.getMaxSpanningTree();
533 #ifdef DEBUG_PATH_PROFILES
534 std::cerr<<"Original maxspanning tree\n";
537 //now edges of tree t have weights reversed
538 //(negative) because the algorithm used
539 //to find max spanning tree is
540 //actually for finding min spanning tree
541 //so get back the original weights
544 //Ordinarily, the graph is directional
545 //lets converts the graph into an
546 //undirectional graph
547 //This is done by adding an edge
548 //v->u for all existing edges u->v
549 t->makeUnDirectional();
551 //Given a tree t, and a "directed graph" g
552 //replace the edges in the tree t with edges that exist in graph
553 //The tree is formed from "undirectional" copy of graph
554 //So whatever edges the tree has, the undirectional graph
555 //would have too. This function corrects some of the directions in
556 //the tree so that now, all edge directions in the tree match
557 //the edge directions of corresponding edges in the directed graph
558 removeTreeEdges(g, *t);
560 #ifdef DEBUG_PATH_PROFILES
561 cerr<<"Final Spanning tree---------\n";
563 cerr<<"-------end spanning tree\n";
566 //now remove the exit->root node
567 //and re-add it with weight 0
568 //since infinite weight is kinda confusing
570 Edge edNew(g.getExit(), g.getRoot(),0);
580 //step 5: Get edge increments
582 //Now we select a subset of all edges
583 //and assign them some values such that
584 //if we consider just this subset, it still represents
585 //the path sum along any path in the graph
587 map<Edge, int, EdgeCompare2> increment=getEdgeIncrements(g,*t, be);
588 #ifdef DEBUG_PATH_PROFILES
589 //print edge increments for debugging
590 std::cerr<<"Edge Increments------\n";
591 for(map<Edge, int, EdgeCompare2>::iterator MMI=increment.begin(), MME=increment.end(); MMI != MME; ++MMI){
592 printEdge(MMI->first);
593 std::cerr<<"Increment for above:"<<MMI->second<<"\n";
595 std::cerr<<"-------end of edge increments\n";
599 //step 6: Get code insertions
601 //Based on edgeIncrements (above), now obtain
602 //the kind of code to be inserted along an edge
603 //The idea here is to minimize the computation
604 //by inserting only the needed code
606 getChords(chords, g, *t);
609 map<Edge, getEdgeCode *, EdgeCompare2> codeInsertions;
610 getCodeInsertions(g, codeInsertions, chords,increment);
612 #ifdef DEBUG_PATH_PROFILES
613 //print edges with code for debugging
614 cerr<<"Code inserted in following---------------\n";
615 for(map<Edge, getEdgeCode *, EdgeCompare2>::iterator cd_i=codeInsertions.begin(),
616 cd_e=codeInsertions.end(); cd_i!=cd_e; ++cd_i){
617 printEdge(cd_i->first);
618 cerr<<cd_i->second->getCond()<<":"<<cd_i->second->getInc()<<"\n";
620 cerr<<"-----end insertions\n";
623 //step 7: move code on dummy edges over to the back edges
625 //Move the incoming dummy edge code and outgoing dummy
626 //edge code over to the corresponding back edge
628 moveDummyCode(stDummy, exDummy, be, codeInsertions, g);
630 #ifdef DEBUG_PATH_PROFILES
632 cerr<<"After moving dummy code\n";
633 for(map<Edge, getEdgeCode *>::iterator cd_i=codeInsertions.begin(),
634 cd_e=codeInsertions.end(); cd_i != cd_e; ++cd_i){
635 printEdge(cd_i->first);
636 cerr<<cd_i->second->getCond()<<":"
637 <<cd_i->second->getInc()<<"\n";
639 cerr<<"Dummy end------------\n";
643 //see what it looks like...
644 //now insert code along edges which have codes on them
645 for(map<Edge, getEdgeCode *>::iterator MI=codeInsertions.begin(),
646 ME=codeInsertions.end(); MI!=ME; ++MI){
648 insertBB(ed, MI->second, rInst, countInst, numPaths, MethNo, threshold);
652 //print the graph (for debugging)
653 void printGraph(Graph &g){
654 vector<Node *> lt=g.getAllNodes();
655 cerr<<"Graph---------------------\n";
656 for(vector<Node *>::iterator LI=lt.begin();
658 cerr<<((*LI)->getElement())->getName()<<"->";
659 Graph::nodeList nl=g.getNodeList(*LI);
660 for(Graph::nodeList::iterator NI=nl.begin();
662 cerr<<":"<<"("<<(NI->element->getElement())
663 ->getName()<<":"<<NI->element->getWeight()<<","<<NI->weight<<","
668 cerr<<"--------------------Graph\n";