mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-23 15:29:51 +00:00
9d80930e95
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@21480 91177308-0d34-0410-b5e6-96231b3b80d8
481 lines
14 KiB
C++
481 lines
14 KiB
C++
//===-- Graph.h -------------------------------------------------*- C++ -*-===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file was developed by the LLVM research group and is distributed under
|
|
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// 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>
|
|
|
|
namespace llvm {
|
|
|
|
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;
|
|
}
|
|
};
|
|
|
|
} // End llvm namespace
|
|
|
|
|
|
namespace std {
|
|
|
|
using namespace llvm;
|
|
|
|
template<>
|
|
struct less<Node *> : public binary_function<Node *, Node *,bool> {
|
|
bool operator()(Node *n1, Node *n2) const {
|
|
return n1->getElement() < n2->getElement();
|
|
}
|
|
};
|
|
|
|
template<>
|
|
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));
|
|
}
|
|
};
|
|
}
|
|
|
|
namespace llvm {
|
|
|
|
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);
|
|
|
|
} // End llvm namespace
|
|
|
|
#endif
|