summaryrefslogtreecommitdiff
path: root/lib/Transforms/Instrumentation/ProfilePaths/Graph.h
blob: 3c22d627e4fbb4e05360377e32afc433a1a0a834 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
//===-- ------------------------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 <map>
#include <cstdlib>

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<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 EdgeCompare2{
  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();
    double r1 = e1.getRandId();
    double r2 = e2.getRandId();
    //return (*x1<*y1 || (*x1==*y1 && *x2<*y2) || (*x1==*y1 && *x2==*y2 && w1<w2));
    return (*x1<*y1 || (*x1==*y1 && *x2<*y2) || (*x1==*y1 && *x2==*y2 && w1<w2) || (*x1==*y1 && *x2==*y2 && w1==w2 && r1<r2));
  }
};

//struct EdgeCompare2{
//bool operator()(Edge e1, Edge e2) const {
//  assert(!e1.isNull() && !e2.isNull());
//  return (e1.getRandId()<e2.getRandId());
//}
//};


//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);

  //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);

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);

  //check whether graph has an edge, with a given wt
  bool hasEdgeAndWt(Edge ed);

  //get the list of successor nodes
  std::vector<Node *> getSuccNodes(Node *nd);

  //get the number of outgoing edges
  int getNumberOfOutgoingEdges(Node *nd) const;

  //get the list of predecessor nodes
  std::vector<Node *> 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<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();
  
  //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, std::map<Node *, int> &d);

  nodeList &sortNodeList(Node *par, nodeList &nl, std::vector<Edge> &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<Edge> &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<Value *> &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<Edge> &be, std::vector<Edge> &stDummy, std::vector<Edge> &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<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, std::map<Node *, int> nodePriority, 
                           std::vector<Edge> &be);

void getBBtrace(std::vector<BasicBlock *> &vBB, int pathNo, Function *M);
#endif