Relocating Graph.h
authorAnand Shukla <ashukla@cs.uiuc.edu>
Tue, 25 Jun 2002 14:28:55 +0000 (14:28 +0000)
committerAnand Shukla <ashukla@cs.uiuc.edu>
Tue, 25 Jun 2002 14:28:55 +0000 (14:28 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@2770 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/Instrumentation/ProfilePaths/Graph.h [new file with mode: 0644]

diff --git a/lib/Transforms/Instrumentation/ProfilePaths/Graph.h b/lib/Transforms/Instrumentation/ProfilePaths/Graph.h
new file mode 100644 (file)
index 0000000..22280d2
--- /dev/null
@@ -0,0 +1,465 @@
+//===-- ------------------------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 "Support/StatisticReporter.h"
+
+#include <map>
+//#include <list>
+//#include <set>
+#include <vector>
+#include <cstdlib>
+
+#include "llvm/BasicBlock.h"
+
+class BasicBlock;
+//class Method;
+class Module;
+//=======
+class Function;
+//>>>>>>> 1.4
+class Instruction;
+
+//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<nd.element; }
+  inline bool operator==(Node& nd) const { return element==nd.element; }
+};
+////////////////////////
+
+//Class Edge
+//Denotes an edge in the graph
+class Edge{
+private:
+  Node *first;
+  Node *second;
+  bool isnull;
+  int weight;
+  double randId;
+public:
+  inline Edge(Node *f,Node *s, int wt=0){
+    first=f;
+    second=s;
+    weight=wt;
+    randId=rand();
+    isnull=false;
+  }
+  
+  inline Edge(Node *f,Node *s, int wt, double rd){
+    first=f;
+    second=s;
+    weight=wt;
+    randId=rd;
+    isnull=false; 
+  }
+
+  inline Edge() { isnull = true; }
+  inline double getRandId(){ return randId; }
+  inline Node* getFirst() { assert(!isNull()); return first; }
+  inline Node* const getFirst() const { assert(!isNull()); return first; }
+  inline Node* getSecond() { assert(!isNull()); return second; }
+  inline Node* const getSecond() const { assert(!isNull()); return second; }
+  
+  inline int getWeight() { assert(!isNull());  return weight; }
+  inline void setWeight(int n) { assert(!isNull()); weight=n; }
+  
+  inline void setFirst(Node *&f) { assert(!isNull());  first=f; }
+  inline void setSecond(Node *&s) { assert(!isNull()); second=s; }
+  
+  
+  inline bool isNull() const { return isnull;} 
+  
+  inline bool operator<(const Edge& ed) const{
+    // Can't be the same if one is null and the other isn't
+    if (isNull() != ed.isNull())
+      return true;
+
+    return (*first<*(ed.getFirst()))|| 
+      (*first==*(ed.getFirst()) && *second<*(ed.getSecond()));
+  }
+
+  inline bool operator==(const Edge& ed) const{
+    return !(*this<ed) && !(ed<*this);
+  }
+
+  inline bool operator!=(const Edge& ed) const{return !(*this==ed);} 
+};
+////////////////////////
+
+//graphListElement
+//This forms the "adjacency list element" of a 
+//vertex adjacency list in graph
+struct graphListElement{
+  Node *element;
+  int weight;
+  double randId;
+  inline graphListElement(Node *n, int w, double rand){ 
+    element=n; 
+    weight=w;
+    randId=rand;
+  }
+};
+/////////////////////////
+
+namespace std {
+  struct less<Node *> : public binary_function<Node *, Node *,bool> {
+    bool operator()(Node *n1, Node *n2) const {
+      return n1->getElement() < n2->getElement();
+    }
+  };
+
+  struct less<Edge> : public binary_function<Edge,Edge,bool> {
+    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 name1<name2;
+  }
+};
+
+struct NodeListSort{
+  bool operator()(graphListElement BB1, graphListElement BB2) const{
+    std::string name1=BB1.element->getElement()->getName();
+    std::string name2=BB2.element->getElement()->getName();
+    return name1<name2;
+  }
+};
+struct EdgeCompare{
+  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();
+    int w1=e1.getWeight();
+    int w2=e2.getWeight();
+    return (*x1<*y1 || (*x1==*y1 && *x2<*y2) || (*x1==*y1 && *x2==*y2 && w1<w2));
+  }
+};
+
+////////////////////
+
+//this is used to color vertices
+//during DFS
+enum Color{
+  WHITE,
+  GREY,
+  BLACK
+};
+
+
+//For path profiling,
+//We assume that the graph is connected (which is true for
+//any method CFG)
+//We also assume that the graph has single entry and single exit
+//(For this, we make a pass over the graph that ensures this)
+//The graph is a construction over any existing graph of BBs
+//Its a construction "over" existing cfg: with
+//additional features like edges and weights to edges
+
+//graph uses adjacency list representation
+class Graph{
+public:
+  //typedef std::map<Node*, std::list<graphListElement> > nodeMapTy;
+  typedef std::map<Node*, std::vector<graphListElement> > 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<Node *> &toReturn) const;
+
+  //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<Edge > &be,
+                        std::map<Node *, Color> &clr,
+                        std::map<Node *, int> &d, 
+                        int &time) const;
+
+public:
+  typedef nodeMapTy::iterator elementIterator;
+  typedef nodeMapTy::const_iterator constElementIterator;
+  typedef std::vector<graphListElement > nodeList;//chng
+  //typedef std::vector<graphListElement > nodeList;
+
+  //graph constructors
+
+  //empty constructor: then add edges and nodes later on
+  Graph() {}
+  
+  //constructor with root and exit node specified
+  Graph(std::vector<Node*> n, 
+       std::vector<Edge> 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) const;
+
+  //check whether graph has an edge, with a given wt
+  bool hasEdgeAndWt(Edge ed) const;
+
+  //get the list of successor nodes
+  std::vector<Node *> getSuccNodes(Node *nd) const;
+
+  //get the number of outgoing edges
+  int getNumberOfOutgoingEdges(Node *nd) const;
+
+  //get the list of predecessor nodes
+  std::vector<Node *> getPredNodes(Node *nd) const;
+
+
+  //to get the no of incoming edges
+  int getNumberOfIncomingEdges(Node *nd) const;
+
+  //get the list of all the vertices in graph
+  std::vector<Node *> getAllNodes() const;
+  std::vector<Node *> getAllNodes();
+
+  //get a list of nodes in the graph
+  //in r-topological sorted order
+  //note that we assumed graph to be connected
+  std::vector<Node *> reverseTopologicalSort() const;
+  
+  //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<Edge> &be) const;
+  //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 const nodeList &getNodeList(Node *nd) const {
+    constElementIterator nli = nodes.find(nd);
+    assert(nli != nodes.end() && "Node must be in nodes map");
+    return nli->second;
+  }
+
+  inline nodeList &getNodeList(Node *nd) {
+    elementIterator nli = nodes.find(nd);
+    assert(nli != nodes.end() && "Node must be in nodes map");
+    return nli->second;
+  }
+
+  //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)
+  //<<<<<<< Graph.h
+  void getCode(Instruction *a, Instruction *b, Function *M, BasicBlock *BB, 
+              int numPaths, int MethNo);
+  //=======
+  //void getCode(Instruction *a, Instruction *b, Function *F, BasicBlock *BB);
+  //>>>>>>> 1.4
+};
+
+
+//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, Instruction *countInst, std::vector<Edge> &be, std::vector<Edge> &stDummy, std::vector<Edge> &exDummy, int n);
+
+//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, Instruction *countInst, int n, int Methno);
+
+//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, Instruction *countVar);
+
+//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<Edge> &stDummy, std::vector<Edge> &exDummy, Graph &g, std::vector<Edge> &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);
+
+void getBBtrace(std::vector<BasicBlock *> &vBB, int pathNo, Function *M);
+#endif
+
+