//===-- ------------------------llvm/graph.h ---------------------*- C++ -*--=// // //Header file for Graph: This Graph is used by //PathProfiles class, and is used //for detecting proper points in cfg for code insertion // //===----------------------------------------------------------------------===// #ifndef LLVM_GRAPH_H #define LLVM_GRAPH_H #include "llvm/BasicBlock.h" #include #include class Module; class Function; //Class Node //It forms the vertex for the graph class Node{ public: BasicBlock* element; int weight; public: inline Node(BasicBlock* x) { element=x; weight=0; } inline BasicBlock* &getElement() { return element; } inline BasicBlock* const &getElement() const { return element; } inline int getWeight() { return weight; } inline void setElement(BasicBlock* e) { element=e; } inline void setWeight(int w) { weight=w;} inline bool operator<(Node& nd) const { return element : public binary_function { bool operator()(Node *n1, Node *n2) const { return n1->getElement() < n2->getElement(); } }; struct less : public binary_function { bool operator()(Edge e1, Edge e2) const { assert(!e1.isNull() && !e2.isNull()); Node *x1=e1.getFirst(); Node *x2=e1.getSecond(); Node *y1=e2.getFirst(); Node *y2=e2.getSecond(); return (*x1<*y1 ||(*x1==*y1 && *x2<*y2)); } }; } struct BBSort{ bool operator()(BasicBlock *BB1, BasicBlock *BB2) const{ std::string name1=BB1->getName(); std::string name2=BB2->getName(); return name1getElement()->getName(); std::string name2=BB2.element->getElement()->getName(); return name1 > nodeMapTy; typedef std::map > nodeMapTy;//chng private: //the adjacency list of a vertex or node nodeMapTy nodes; //the start or root node Node *strt; //the exit node Node *ext; //a private method for doing DFS traversal of graph //this is used in determining the reverse topological sort //of the graph void DFS_Visit(Node *nd, std::vector &toReturn); //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 getBackEdgesVisit(Node *u, std::vector &be, std::map &clr, std::map &d, int &time); public: typedef nodeMapTy::iterator elementIterator; typedef nodeMapTy::const_iterator constElementIterator; typedef std::vector nodeList;//chng //typedef std::vector nodeList; //graph constructors //empty constructor: then add edges and nodes later on Graph() {} //constructor with root and exit node specified Graph(std::vector n, std::vector e, Node *rt, Node *lt); //add a node void addNode(Node *nd); //add an edge //this adds an edge ONLY when //the edge to be added doesn not already exist //we "equate" two edges here only with their //end points void addEdge(Edge ed, int w); //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 addEdgeForce(Edge ed); //set the weight of an edge void setWeight(Edge ed); //remove an edge //Note that it removes just one edge, //the first edge that is encountered void removeEdge(Edge ed); //remove edge with given wt void removeEdgeWithWt(Edge ed); //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 //it may possibly have different weight though bool hasEdge(Edge ed); //check whether graph has an edge, with a given wt bool hasEdgeAndWt(Edge ed); //get the list of successor nodes std::vector getSuccNodes(Node *nd); //get the number of outgoing edges int getNumberOfOutgoingEdges(Node *nd) const; //get the list of predecessor nodes std::vector getPredNodes(Node *nd); //to get the no of incoming edges int getNumberOfIncomingEdges(Node *nd); //get the list of all the vertices in graph std::vector getAllNodes() const; std::vector getAllNodes(); //get a list of nodes in the graph //in r-topological sorted order //note that we assumed graph to be connected std::vector reverseTopologicalSort(); //reverse the sign of weights on edges //this way, max-spanning tree could be obtained //usin min-spanning tree, and vice versa void reverseWts(); //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 makeUnDirectional(); //print graph: for debugging void printGraph(); //get a vector of back edges in the graph void getBackEdges(std::vector &be, std::map &d); nodeList &sortNodeList(Node *par, nodeList &nl, std::vector &be); //Get the Maximal spanning tree (also a graph) //of the graph Graph* getMaxSpanningTree(); //get the nodeList adjacent to a node //a nodeList element contains a node, and the weight //corresponding to the edge for that element inline nodeList &getNodeList(Node *nd) { elementIterator nli = nodes.find(nd); assert(nli != nodes.end() && "Node must be in nodes map"); return nodes[nd];//sortNodeList(nd, nli->second); } nodeList &getSortedNodeList(Node *nd, std::vector &be) { elementIterator nli = nodes.find(nd); assert(nli != nodes.end() && "Node must be in nodes map"); return sortNodeList(nd, nodes[nd], be); } //get the root of the graph inline Node *getRoot() {return strt; } inline Node * const getRoot() const {return strt; } //get exit: we assumed there IS a unique exit :) inline Node *getExit() {return ext; } inline Node * const getExit() const {return ext; } //Check if a given node is the root inline bool isRoot(Node *n) const {return (*n==*strt); } //check if a given node is leaf node //here we hv only 1 leaf: which is the exit node inline bool isLeaf(Node *n) const {return (*n==*ext); } }; //This class is used to generate //"appropriate" code to be inserted //along an edge //The code to be inserted can be of six different types //as given below //1: r=k (where k is some constant) //2: r=0 //3: r+=k //4: count[k]++ //5: Count[r+k]++ //6: Count[r]++ class getEdgeCode{ private: //cond implies which //"kind" of code is to be inserted //(from 1-6 above) int cond; //inc is the increment: eg k, or 0 int inc; //A backedge must carry the code //of both incoming "dummy" edge //and outgoing "dummy" edge //If a->b is a backedge //then incoming dummy edge is root->b //and outgoing dummy edge is a->exit //incoming dummy edge, if any getEdgeCode *cdIn; //outgoing dummy edge, if any getEdgeCode *cdOut; public: getEdgeCode(){ cdIn=NULL; cdOut=NULL; inc=0; cond=0; } //set condition: 1-6 inline void setCond(int n) {cond=n;} //get the condition inline int getCond() { return cond;} //set increment inline void setInc(int n) {inc=n;} //get increment inline int getInc() {return inc;} //set CdIn (only used for backedges) inline void setCdIn(getEdgeCode *gd){ cdIn=gd;} //set CdOut (only used for backedges) inline void setCdOut(getEdgeCode *gd){ cdOut=gd;} //get the code to be inserted on the edge //This is determined from cond (1-6) void getCode(Instruction *a, Value *b, Function *M, BasicBlock *BB, std::vector &retVec); }; //auxillary functions on graph //print a given edge in the form BB1Label->BB2Label void printEdge(Edge ed); //Do graph processing: to determine minimal edge increments, //appropriate code insertions etc and insert the code at //appropriate locations void processGraph(Graph &g, Instruction *rInst, Value *countInst, std::vector &be, std::vector &stDummy, std::vector &exDummy, int n, int MethNo, Value *threshold); //print the graph (for debugging) void printGraph(Graph &g); //void printGraph(const Graph g); //insert a basic block with appropriate code //along a given edge void insertBB(Edge ed, getEdgeCode *edgeCode, Instruction *rInst, Value *countInst, int n, int Methno, Value *threshold); //Insert the initialization code in the top BB //this includes initializing r, and count //r is like an accumulator, that //keeps on adding increments as we traverse along a path //and at the end of the path, r contains the path //number of that path //Count is an array, where Count[k] represents //the number of executions of path k void insertInTopBB(BasicBlock *front, int k, Instruction *rVar, Value *threshold); //Add dummy edges corresponding to the back edges //If a->b is a backedge //then incoming dummy edge is root->b //and outgoing dummy edge is a->exit void addDummyEdges(std::vector &stDummy, std::vector &exDummy, Graph &g, std::vector &be); //Assign a value to all the edges in the graph //such that if we traverse along any path from root to exit, and //add up the edge values, we get a path number that uniquely //refers to the path we travelled int valueAssignmentToEdges(Graph& g, std::map nodePriority, std::vector &be); void getBBtrace(std::vector &vBB, int pathNo, Function *M); #endif