Remove some beta code that no longer has an owner.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23944 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chris Lattner 2005-10-24 02:32:41 +00:00
parent a66459095c
commit d00a3cee80
9 changed files with 0 additions and 3043 deletions

View File

@ -1,189 +0,0 @@
//===-- CombineBranch.cpp -------------------------------------------------===//
//
// 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.
//
//===----------------------------------------------------------------------===//
//
// Combine multiple back-edges going to the same sink into a single
// back-edge. This introduces a new basic block and back-edge branch for each
// such sink.
//
//===----------------------------------------------------------------------===//
#include "llvm/Support/CFG.h"
#include "llvm/Instructions.h"
#include "llvm/Function.h"
#include "llvm/Pass.h"
#include "llvm/Type.h"
namespace llvm {
namespace {
struct CombineBranches : public FunctionPass {
private:
/// Possible colors that a vertex can have during depth-first search for
/// back-edges.
///
enum Color { WHITE, GREY, BLACK };
void getBackEdgesVisit(BasicBlock *u,
std::map<BasicBlock *, Color > &color,
std::map<BasicBlock *, int > &d,
int &time,
std::map<BasicBlock *, BasicBlock *> &be);
void removeRedundant(std::map<BasicBlock *, BasicBlock *> &be);
public:
bool runOnFunction(Function &F);
};
RegisterOpt<CombineBranches>
X("branch-combine", "Multiple backedges going to same target are merged");
}
/// getBackEdgesVisit - Get the back-edges of the control-flow graph for this
/// function. We proceed recursively using depth-first search. 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 CombineBranches::getBackEdgesVisit(BasicBlock *u,
std::map<BasicBlock *, Color > &color,
std::map<BasicBlock *, int > &d,
int &time,
std::map<BasicBlock *, BasicBlock *> &be) {
color[u]=GREY;
time++;
d[u]=time;
for (succ_iterator vl = succ_begin(u), ve = succ_end(u); vl != ve; ++vl){
BasicBlock *BB = *vl;
if(color[BB]!=GREY && color[BB]!=BLACK)
getBackEdgesVisit(BB, color, d, time, be);
//now checking for d and f vals
else if(color[BB]==GREY){
//so v is ancestor of u if time of u > time of v
if(d[u] >= d[BB]) // u->BB is a backedge
be[u] = BB;
}
}
color[u]=BLACK;//done with visiting the node and its neighbors
}
/// removeRedundant - Remove all back-edges that are dominated by other
/// back-edges in the set.
///
void CombineBranches::removeRedundant(std::map<BasicBlock *, BasicBlock *> &be){
std::vector<BasicBlock *> toDelete;
std::map<BasicBlock *, int> seenBB;
for(std::map<BasicBlock *, BasicBlock *>::iterator MI = be.begin(),
ME = be.end(); MI != ME; ++MI){
if(seenBB[MI->second])
continue;
seenBB[MI->second] = 1;
std::vector<BasicBlock *> sameTarget;
sameTarget.clear();
for(std::map<BasicBlock *, BasicBlock *>::iterator MMI = be.begin(),
MME = be.end(); MMI != MME; ++MMI){
if(MMI->first == MI->first)
continue;
if(MMI->second == MI->second)
sameTarget.push_back(MMI->first);
}
//so more than one branch to same target
if(sameTarget.size()){
sameTarget.push_back(MI->first);
BasicBlock *newBB = new BasicBlock("newCommon", MI->first->getParent());
BranchInst *newBranch = new BranchInst(MI->second, newBB);
std::map<PHINode *, std::vector<unsigned int> > phiMap;
for(std::vector<BasicBlock *>::iterator VBI = sameTarget.begin(),
VBE = sameTarget.end(); VBI != VBE; ++VBI){
BranchInst *ti = cast<BranchInst>((*VBI)->getTerminator());
unsigned char index = 1;
if(ti->getSuccessor(0) == MI->second)
index = 0;
ti->setSuccessor(index, newBB);
for(BasicBlock::iterator BB2Inst = MI->second->begin(),
BBend = MI->second->end(); BB2Inst != BBend; ++BB2Inst){
if (PHINode *phiInst = dyn_cast<PHINode>(BB2Inst)){
int bbIndex;
bbIndex = phiInst->getBasicBlockIndex(*VBI);
if(bbIndex>=0)
phiMap[phiInst].push_back(bbIndex);
}
}
}
for(std::map<PHINode *, std::vector<unsigned int> >::iterator
PI = phiMap.begin(), PE = phiMap.end(); PI != PE; ++PI){
PHINode *phiNode = new PHINode(PI->first->getType(), "phi", newBranch);
for(std::vector<unsigned int>::iterator II = PI->second.begin(),
IE = PI->second.end(); II != IE; ++II){
phiNode->addIncoming(PI->first->getIncomingValue(*II),
PI->first->getIncomingBlock(*II));
}
std::vector<BasicBlock *> tempBB;
for(std::vector<unsigned int>::iterator II = PI->second.begin(),
IE = PI->second.end(); II != IE; ++II){
tempBB.push_back(PI->first->getIncomingBlock(*II));
}
for(std::vector<BasicBlock *>::iterator II = tempBB.begin(),
IE = tempBB.end(); II != IE; ++II){
PI->first->removeIncomingValue(*II);
}
PI->first->addIncoming(phiNode, newBB);
}
}
}
}
/// runOnFunction - Per function pass for combining branches.
///
bool CombineBranches::runOnFunction(Function &F){
if (F.isExternal ())
return false;
// Find and remove "redundant" back-edges.
std::map<BasicBlock *, Color> color;
std::map<BasicBlock *, int> d;
std::map<BasicBlock *, BasicBlock *> be;
int time = 0;
getBackEdgesVisit (F.begin (), color, d, time, be);
removeRedundant (be);
return true; // FIXME: assumes a modification was always made.
}
FunctionPass *createCombineBranchesPass () {
return new CombineBranches();
}
} // End llvm namespace

View File

@ -1,368 +0,0 @@
//===-- EdgeCode.cpp - generate LLVM instrumentation code -----------------===//
//
// 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.
//
//===----------------------------------------------------------------------===//
//It implements the class EdgeCode: which provides
//support for inserting "appropriate" instrumentation at
//designated points in the graph
//
//It also has methods to insert initialization code in
//top block of cfg
//===----------------------------------------------------------------------===//
#include "Graph.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Instructions.h"
#include "llvm/Module.h"
#define INSERT_LOAD_COUNT
#define INSERT_STORE
using std::vector;
namespace llvm {
static void getTriggerCode(Module *M, BasicBlock *BB, int MethNo, Value *pathNo,
Value *cnt, Instruction *rInst){
vector<Value *> tmpVec;
tmpVec.push_back(Constant::getNullValue(Type::LongTy));
tmpVec.push_back(Constant::getNullValue(Type::LongTy));
Instruction *Idx = new GetElementPtrInst(cnt, tmpVec, "");//,
BB->getInstList().push_back(Idx);
const Type *PIntTy = PointerType::get(Type::IntTy);
Function *trigMeth = M->getOrInsertFunction("trigger", Type::VoidTy,
Type::IntTy, Type::IntTy,
PIntTy, PIntTy, (Type *)0);
assert(trigMeth && "trigger method could not be inserted!");
vector<Value *> trargs;
trargs.push_back(ConstantSInt::get(Type::IntTy,MethNo));
trargs.push_back(pathNo);
trargs.push_back(Idx);
trargs.push_back(rInst);
Instruction *callInst=new CallInst(trigMeth, trargs, "");//, BB->begin());
BB->getInstList().push_back(callInst);
//triggerInst = new CallInst(trigMeth, trargs, "");//, InsertPos);
}
//get the code to be inserted on the edge
//This is determined from cond (1-6)
void getEdgeCode::getCode(Instruction *rInst, Value *countInst,
Function *M, BasicBlock *BB,
vector<Value *> &retVec){
//Instruction *InsertPos = BB->getInstList().begin();
//now check for cdIn and cdOut
//first put cdOut
if(cdOut!=NULL){
cdOut->getCode(rInst, countInst, M, BB, retVec);
}
if(cdIn!=NULL){
cdIn->getCode(rInst, countInst, M, BB, retVec);
}
//case: r=k code to be inserted
switch(cond){
case 1:{
Value *val=ConstantSInt::get(Type::IntTy,inc);
#ifdef INSERT_STORE
Instruction *stInst=new StoreInst(val, rInst);//, InsertPos);
BB->getInstList().push_back(stInst);
#endif
break;
}
//case: r=0 to be inserted
case 2:{
#ifdef INSERT_STORE
Instruction *stInst = new StoreInst(ConstantSInt::getNullValue(Type::IntTy), rInst);//, InsertPos);
BB->getInstList().push_back(stInst);
#endif
break;
}
//r+=k
case 3:{
Instruction *ldInst = new LoadInst(rInst, "ti1");//, InsertPos);
BB->getInstList().push_back(ldInst);
Value *val = ConstantSInt::get(Type::IntTy,inc);
Instruction *addIn = BinaryOperator::create(Instruction::Add, ldInst, val,
"ti2");//, InsertPos);
BB->getInstList().push_back(addIn);
#ifdef INSERT_STORE
Instruction *stInst = new StoreInst(addIn, rInst);//, InsertPos);
BB->getInstList().push_back(stInst);
#endif
break;
}
//count[inc]++
case 4:{
vector<Value *> tmpVec;
tmpVec.push_back(Constant::getNullValue(Type::LongTy));
tmpVec.push_back(ConstantSInt::get(Type::LongTy, inc));
Instruction *Idx = new GetElementPtrInst(countInst, tmpVec, "");//,
//Instruction *Idx = new GetElementPtrInst(countInst,
// vector<Value*>(1,ConstantSInt::get(Type::LongTy, inc)),
// "");//, InsertPos);
BB->getInstList().push_back(Idx);
Instruction *ldInst=new LoadInst(Idx, "ti1");//, InsertPos);
BB->getInstList().push_back(ldInst);
Value *val = ConstantSInt::get(Type::IntTy, 1);
//Instruction *addIn =
Instruction *newCount =
BinaryOperator::create(Instruction::Add, ldInst, val,"ti2");
BB->getInstList().push_back(newCount);
#ifdef INSERT_STORE
//Instruction *stInst=new StoreInst(addIn, Idx, InsertPos);
Instruction *stInst=new StoreInst(newCount, Idx);//, InsertPos);
BB->getInstList().push_back(stInst);
#endif
Value *trAddIndex = ConstantSInt::get(Type::IntTy,inc);
retVec.push_back(newCount);
retVec.push_back(trAddIndex);
//insert trigger
//getTriggerCode(M->getParent(), BB, MethNo,
// ConstantSInt::get(Type::IntTy,inc), newCount, triggerInst);
//end trigger code
assert(inc>=0 && "IT MUST BE POSITIVE NOW");
break;
}
//case: count[r+inc]++
case 5:{
//ti1=inc+r
Instruction *ldIndex=new LoadInst(rInst, "ti1");//, InsertPos);
BB->getInstList().push_back(ldIndex);
Value *val=ConstantSInt::get(Type::IntTy,inc);
Instruction *addIndex=BinaryOperator::
create(Instruction::Add, ldIndex, val,"ti2");//, InsertPos);
BB->getInstList().push_back(addIndex);
//now load count[addIndex]
Instruction *castInst=new CastInst(addIndex,
Type::LongTy,"ctin");//, InsertPos);
BB->getInstList().push_back(castInst);
vector<Value *> tmpVec;
tmpVec.push_back(Constant::getNullValue(Type::LongTy));
tmpVec.push_back(castInst);
Instruction *Idx = new GetElementPtrInst(countInst, tmpVec, "");//,
// InsertPos);
BB->getInstList().push_back(Idx);
Instruction *ldInst=new LoadInst(Idx, "ti3");//, InsertPos);
BB->getInstList().push_back(ldInst);
Value *cons=ConstantSInt::get(Type::IntTy,1);
//count[addIndex]++
//std::cerr<<"Type ldInst:"<<ldInst->getType()<<"\t cons:"<<cons->getType()<<"\n";
Instruction *newCount = BinaryOperator::create(Instruction::Add, ldInst,
cons,"");
BB->getInstList().push_back(newCount);
#ifdef INSERT_STORE
Instruction *stInst = new StoreInst(newCount, Idx);//, InsertPos);
BB->getInstList().push_back(stInst);
#endif
retVec.push_back(newCount);
retVec.push_back(addIndex);
//insert trigger
//getTriggerCode(M->getParent(), BB, MethNo, addIndex, newCount, triggerInst);
//end trigger code
break;
}
//case: count[r]+
case 6:{
//ti1=inc+r
Instruction *ldIndex=new LoadInst(rInst, "ti1");//, InsertPos);
BB->getInstList().push_back(ldIndex);
//now load count[addIndex]
Instruction *castInst2=new CastInst(ldIndex, Type::LongTy,"ctin");
BB->getInstList().push_back(castInst2);
vector<Value *> tmpVec;
tmpVec.push_back(Constant::getNullValue(Type::LongTy));
tmpVec.push_back(castInst2);
Instruction *Idx = new GetElementPtrInst(countInst, tmpVec, "");//,
//Instruction *Idx = new GetElementPtrInst(countInst,
// vector<Value*>(1,castInst2), "");
BB->getInstList().push_back(Idx);
Instruction *ldInst=new LoadInst(Idx, "ti2");//, InsertPos);
BB->getInstList().push_back(ldInst);
Value *cons=ConstantSInt::get(Type::IntTy,1);
//count[addIndex]++
Instruction *newCount = BinaryOperator::create(Instruction::Add, ldInst,
cons,"ti3");
BB->getInstList().push_back(newCount);
#ifdef INSERT_STORE
Instruction *stInst = new StoreInst(newCount, Idx);//, InsertPos);
BB->getInstList().push_back(stInst);
#endif
retVec.push_back(newCount);
retVec.push_back(ldIndex);
break;
}
}
}
//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){
//rVar is variable r,
//countVar is count[]
Value *Int0 = ConstantInt::get(Type::IntTy, 0);
//now push all instructions in front of the BB
BasicBlock::iterator here=front->begin();
front->getInstList().insert(here, rVar);
//front->getInstList().insert(here,countVar);
//Initialize Count[...] with 0
//for (int i=0;i<k; i++){
//Value *GEP2 = new GetElementPtrInst(countVar,
// vector<Value *>(1,ConstantSInt::get(Type::LongTy, i)),
// "", here);
//new StoreInst(Int0, GEP2, here);
//}
//store uint 0, uint *%R
new StoreInst(Int0, rVar, here);
}
//insert a basic block with appropriate code
//along a given edge
void insertBB(Edge ed,
getEdgeCode *edgeCode,
Instruction *rInst,
Value *countInst,
int numPaths, int Methno, Value *threshold){
BasicBlock* BB1=ed.getFirst()->getElement();
BasicBlock* BB2=ed.getSecond()->getElement();
#ifdef DEBUG_PATH_PROFILES
//debugging info
cerr<<"Edges with codes ######################\n";
cerr<<BB1->getName()<<"->"<<BB2->getName()<<"\n";
cerr<<"########################\n";
#endif
//We need to insert a BB between BB1 and BB2
TerminatorInst *TI=BB1->getTerminator();
BasicBlock *newBB=new BasicBlock("counter", BB1->getParent());
//get code for the new BB
vector<Value *> retVec;
edgeCode->getCode(rInst, countInst, BB1->getParent(), newBB, retVec);
BranchInst *BI = cast<BranchInst>(TI);
//Is terminator a branch instruction?
//then we need to change branch destinations to include new BB
if(BI->isUnconditional()){
BI->setUnconditionalDest(newBB);
}
else{
if(BI->getSuccessor(0)==BB2)
BI->setSuccessor(0, newBB);
if(BI->getSuccessor(1)==BB2)
BI->setSuccessor(1, newBB);
}
BasicBlock *triggerBB = NULL;
if(retVec.size()>0){
triggerBB = new BasicBlock("trigger", BB1->getParent());
getTriggerCode(BB1->getParent()->getParent(), triggerBB, Methno,
retVec[1], countInst, rInst);//retVec[0]);
//Instruction *castInst = new CastInst(retVec[0], Type::IntTy, "");
Instruction *etr = new LoadInst(threshold, "threshold");
//std::cerr<<"type1: "<<etr->getType()<<" type2: "<<retVec[0]->getType()<<"\n";
Instruction *cmpInst = new SetCondInst(Instruction::SetLE, etr,
retVec[0], "");
Instruction *newBI2 = new BranchInst(triggerBB, BB2, cmpInst);
//newBB->getInstList().push_back(castInst);
newBB->getInstList().push_back(etr);
newBB->getInstList().push_back(cmpInst);
newBB->getInstList().push_back(newBI2);
//triggerBB->getInstList().push_back(triggerInst);
new BranchInst(BB2, 0, 0, triggerBB);
}
else{
new BranchInst(BB2, 0, 0, newBB);
}
//now iterate over BB2, and set its Phi nodes right
for(BasicBlock::iterator BB2Inst = BB2->begin(), BBend = BB2->end();
BB2Inst != BBend; ++BB2Inst){
if(PHINode *phiInst=dyn_cast<PHINode>(BB2Inst)){
int bbIndex=phiInst->getBasicBlockIndex(BB1);
assert(bbIndex>=0);
phiInst->setIncomingBlock(bbIndex, newBB);
///check if trigger!=null, then add value corresponding to it too!
if(retVec.size()>0){
assert(triggerBB && "BasicBlock with trigger should not be null!");
Value *vl = phiInst->getIncomingValue((unsigned int)bbIndex);
phiInst->addIncoming(vl, triggerBB);
}
}
}
}
} // End llvm namespace

View File

@ -1,569 +0,0 @@
//===-- Graph.cpp - Implements Graph class --------------------------------===//
//
// 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.
//
//===----------------------------------------------------------------------===//
//
// This implements Graph for helping in trace generation This graph gets used by
// "ProfilePaths" class.
//
//===----------------------------------------------------------------------===//
#include "Graph.h"
#include "llvm/Instructions.h"
#include "llvm/Support/Debug.h"
#include <algorithm>
using std::vector;
namespace llvm {
const graphListElement *findNodeInList(const Graph::nodeList &NL,
Node *N) {
for(Graph::nodeList::const_iterator NI = NL.begin(), NE=NL.end(); NI != NE;
++NI)
if (*NI->element== *N)
return &*NI;
return 0;
}
graphListElement *findNodeInList(Graph::nodeList &NL, Node *N) {
for(Graph::nodeList::iterator NI = NL.begin(), NE=NL.end(); NI != NE; ++NI)
if (*NI->element== *N)
return &*NI;
return 0;
}
//graph constructor with root and exit specified
Graph::Graph(std::vector<Node*> n, std::vector<Edge> e,
Node *rt, Node *lt){
strt=rt;
ext=lt;
for(vector<Node* >::iterator x=n.begin(), en=n.end(); x!=en; ++x)
//nodes[*x] = list<graphListElement>();
nodes[*x] = vector<graphListElement>();
for(vector<Edge >::iterator x=e.begin(), en=e.end(); x!=en; ++x){
Edge ee=*x;
int w=ee.getWeight();
//nodes[ee.getFirst()].push_front(graphListElement(ee.getSecond(),w, ee.getRandId()));
nodes[ee.getFirst()].push_back(graphListElement(ee.getSecond(),w, ee.getRandId()));
}
}
//sorting edgelist, called by backEdgeVist ONLY!!!
Graph::nodeList &Graph::sortNodeList(Node *par, nodeList &nl, vector<Edge> &be){
assert(par && "null node pointer");
BasicBlock *bbPar = par->getElement();
if(nl.size()<=1) return nl;
if(getExit() == par) return nl;
for(nodeList::iterator NLI = nl.begin(), NLE = nl.end()-1; NLI != NLE; ++NLI){
nodeList::iterator min = NLI;
for(nodeList::iterator LI = NLI+1, LE = nl.end(); LI!=LE; ++LI){
//if LI < min, min = LI
if(min->element->getElement() == LI->element->getElement() &&
min->element == getExit()){
//same successors: so might be exit???
//if it is exit, then see which is backedge
//check if LI is a left back edge!
TerminatorInst *tti = par->getElement()->getTerminator();
BranchInst *ti = cast<BranchInst>(tti);
assert(ti && "not a branch");
assert(ti->getNumSuccessors()==2 && "less successors!");
BasicBlock *tB = ti->getSuccessor(0);
BasicBlock *fB = ti->getSuccessor(1);
//so one of LI or min must be back edge!
//Algo: if succ(0)!=LI (and so !=min) then succ(0) is backedge
//and then see which of min or LI is backedge
//THEN if LI is in be, then min=LI
if(LI->element->getElement() != tB){//so backedge must be made min!
for(vector<Edge>::iterator VBEI = be.begin(), VBEE = be.end();
VBEI != VBEE; ++VBEI){
if(VBEI->getRandId() == LI->randId){
min = LI;
break;
}
else if(VBEI->getRandId() == min->randId)
break;
}
}
else{// if(LI->element->getElement() != fB)
for(vector<Edge>::iterator VBEI = be.begin(), VBEE = be.end();
VBEI != VBEE; ++VBEI){
if(VBEI->getRandId() == min->randId){
min = LI;
break;
}
else if(VBEI->getRandId() == LI->randId)
break;
}
}
}
else if (min->element->getElement() != LI->element->getElement()){
TerminatorInst *tti = par->getElement()->getTerminator();
BranchInst *ti = cast<BranchInst>(tti);
assert(ti && "not a branch");
if(ti->getNumSuccessors()<=1) continue;
assert(ti->getNumSuccessors()==2 && "less successors!");
BasicBlock *tB = ti->getSuccessor(0);
BasicBlock *fB = ti->getSuccessor(1);
if(tB == LI->element->getElement() || fB == min->element->getElement())
min = LI;
}
}
graphListElement tmpElmnt = *min;
*min = *NLI;
*NLI = tmpElmnt;
}
return nl;
}
//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
bool Graph::hasEdge(Edge ed){
if(ed.isNull())
return false;
nodeList &nli= nodes[ed.getFirst()]; //getNodeList(ed.getFirst());
Node *nd2=ed.getSecond();
return (findNodeInList(nli,nd2)!=NULL);
}
//check whether graph has an edge, with a given wt
//having an edge simply means that there is an edge in the graph
//which has same endpoints as the given edge
//This function checks, moreover, that the wt of edge matches too
bool Graph::hasEdgeAndWt(Edge ed){
if(ed.isNull())
return false;
Node *nd2=ed.getSecond();
nodeList &nli = nodes[ed.getFirst()];//getNodeList(ed.getFirst());
for(nodeList::iterator NI=nli.begin(), NE=nli.end(); NI!=NE; ++NI)
if(*NI->element == *nd2 && ed.getWeight()==NI->weight)
return true;
return false;
}
//add a node
void Graph::addNode(Node *nd){
vector<Node *> lt=getAllNodes();
for(vector<Node *>::iterator LI=lt.begin(), LE=lt.end(); LI!=LE;++LI){
if(**LI==*nd)
return;
}
//chng
nodes[nd] =vector<graphListElement>(); //list<graphListElement>();
}
//add an edge
//this adds an edge ONLY when
//the edge to be added does not already exist
//we "equate" two edges here only with their
//end points
void Graph::addEdge(Edge ed, int w){
nodeList &ndList = nodes[ed.getFirst()];
Node *nd2=ed.getSecond();
if(findNodeInList(nodes[ed.getFirst()], nd2))
return;
//ndList.push_front(graphListElement(nd2,w, ed.getRandId()));
ndList.push_back(graphListElement(nd2,w, ed.getRandId()));//chng
//sortNodeList(ed.getFirst(), ndList);
//sort(ndList.begin(), ndList.end(), NodeListSort());
}
//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 Graph::addEdgeForce(Edge ed){
//nodes[ed.getFirst()].push_front(graphListElement(ed.getSecond(),
//ed.getWeight(), ed.getRandId()));
nodes[ed.getFirst()].push_back
(graphListElement(ed.getSecond(), ed.getWeight(), ed.getRandId()));
//sortNodeList(ed.getFirst(), nodes[ed.getFirst()]);
//sort(nodes[ed.getFirst()].begin(), nodes[ed.getFirst()].end(), NodeListSort());
}
//remove an edge
//Note that it removes just one edge,
//the first edge that is encountered
void Graph::removeEdge(Edge ed){
nodeList &ndList = nodes[ed.getFirst()];
Node &nd2 = *ed.getSecond();
for(nodeList::iterator NI=ndList.begin(), NE=ndList.end(); NI!=NE ;++NI) {
if(*NI->element == nd2) {
ndList.erase(NI);
break;
}
}
}
//remove an edge with a given wt
//Note that it removes just one edge,
//the first edge that is encountered
void Graph::removeEdgeWithWt(Edge ed){
nodeList &ndList = nodes[ed.getFirst()];
Node &nd2 = *ed.getSecond();
for(nodeList::iterator NI=ndList.begin(), NE=ndList.end(); NI!=NE ;++NI) {
if(*NI->element == nd2 && NI->weight==ed.getWeight()) {
ndList.erase(NI);
break;
}
}
}
//set the weight of an edge
void Graph::setWeight(Edge ed){
graphListElement *El = findNodeInList(nodes[ed.getFirst()], ed.getSecond());
if (El)
El->weight=ed.getWeight();
}
//get the list of successor nodes
vector<Node *> Graph::getSuccNodes(Node *nd){
nodeMapTy::const_iterator nli = nodes.find(nd);
assert(nli != nodes.end() && "Node must be in nodes map");
const nodeList &nl = getNodeList(nd);//getSortedNodeList(nd);
vector<Node *> lt;
for(nodeList::const_iterator NI=nl.begin(), NE=nl.end(); NI!=NE; ++NI)
lt.push_back(NI->element);
return lt;
}
//get the number of outgoing edges
int Graph::getNumberOfOutgoingEdges(Node *nd) const {
nodeMapTy::const_iterator nli = nodes.find(nd);
assert(nli != nodes.end() && "Node must be in nodes map");
const nodeList &nl = nli->second;
int count=0;
for(nodeList::const_iterator NI=nl.begin(), NE=nl.end(); NI!=NE; ++NI)
count++;
return count;
}
//get the list of predecessor nodes
vector<Node *> Graph::getPredNodes(Node *nd){
vector<Node *> lt;
for(nodeMapTy::const_iterator EI=nodes.begin(), EE=nodes.end(); EI!=EE ;++EI){
Node *lnode=EI->first;
const nodeList &nl = getNodeList(lnode);
const graphListElement *N = findNodeInList(nl, nd);
if (N) lt.push_back(lnode);
}
return lt;
}
//get the number of predecessor nodes
int Graph::getNumberOfIncomingEdges(Node *nd){
int count=0;
for(nodeMapTy::const_iterator EI=nodes.begin(), EE=nodes.end(); EI!=EE ;++EI){
Node *lnode=EI->first;
const nodeList &nl = getNodeList(lnode);
for(Graph::nodeList::const_iterator NI = nl.begin(), NE=nl.end(); NI != NE;
++NI)
if (*NI->element== *nd)
count++;
}
return count;
}
//get the list of all the vertices in graph
vector<Node *> Graph::getAllNodes() const{
vector<Node *> lt;
for(nodeMapTy::const_iterator x=nodes.begin(), en=nodes.end(); x != en; ++x)
lt.push_back(x->first);
return lt;
}
//get the list of all the vertices in graph
vector<Node *> Graph::getAllNodes(){
vector<Node *> lt;
for(nodeMapTy::const_iterator x=nodes.begin(), en=nodes.end(); x != en; ++x)
lt.push_back(x->first);
return lt;
}
//class to compare two nodes in graph
//based on their wt: this is used in
//finding the maximal spanning tree
struct compare_nodes {
bool operator()(Node *n1, Node *n2){
return n1->getWeight() < n2->getWeight();
}
};
static void printNode(Node *nd){
std::cerr<<"Node:"<<nd->getElement()->getName()<<"\n";
}
//Get the Maximal spanning tree (also a graph)
//of the graph
Graph* Graph::getMaxSpanningTree(){
//assume connected graph
Graph *st=new Graph();//max spanning tree, undirected edges
int inf=9999999;//largest key
vector<Node *> lt = getAllNodes();
//initially put all vertices in vector vt
//assign wt(root)=0
//wt(others)=infinity
//
//now:
//pull out u: a vertex frm vt of min wt
//for all vertices w in vt,
//if wt(w) greater than
//the wt(u->w), then assign
//wt(w) to be wt(u->w).
//
//make parent(u)=w in the spanning tree
//keep pulling out vertices from vt till it is empty
vector<Node *> vt;
std::map<Node*, Node* > parent;
std::map<Node*, int > ed_weight;
//initialize: wt(root)=0, wt(others)=infinity
//parent(root)=NULL, parent(others) not defined (but not null)
for(vector<Node *>::iterator LI=lt.begin(), LE=lt.end(); LI!=LE; ++LI){
Node *thisNode=*LI;
if(*thisNode == *getRoot()){
thisNode->setWeight(0);
parent[thisNode]=NULL;
ed_weight[thisNode]=0;
}
else{
thisNode->setWeight(inf);
}
st->addNode(thisNode);//add all nodes to spanning tree
//we later need to assign edges in the tree
vt.push_back(thisNode); //pushed all nodes in vt
}
//keep pulling out vertex of min wt from vt
while(!vt.empty()){
Node *u=*(std::min_element(vt.begin(), vt.end(), compare_nodes()));
DEBUG(std::cerr<<"popped wt"<<(u)->getWeight()<<"\n";
printNode(u));
if(parent[u]!=NULL){ //so not root
Edge edge(parent[u],u, ed_weight[u]); //assign edge in spanning tree
st->addEdge(edge,ed_weight[u]);
DEBUG(std::cerr<<"added:\n";
printEdge(edge));
}
//vt.erase(u);
//remove u frm vt
for(vector<Node *>::iterator VI=vt.begin(), VE=vt.end(); VI!=VE; ++VI){
if(**VI==*u){
vt.erase(VI);
break;
}
}
//assign wt(v) to all adjacent vertices v of u
//only if v is in vt
Graph::nodeList &nl = getNodeList(u);
for(nodeList::iterator NI=nl.begin(), NE=nl.end(); NI!=NE; ++NI){
Node *v=NI->element;
int weight=-NI->weight;
//check if v is in vt
bool contains=false;
for(vector<Node *>::iterator VI=vt.begin(), VE=vt.end(); VI!=VE; ++VI){
if(**VI==*v){
contains=true;
break;
}
}
DEBUG(std::cerr<<"wt:v->wt"<<weight<<":"<<v->getWeight()<<"\n";
printNode(v);std::cerr<<"node wt:"<<(*v).weight<<"\n");
//so if v in in vt, change wt(v) to wt(u->v)
//only if wt(u->v)<wt(v)
if(contains && weight<v->getWeight()){
parent[v]=u;
ed_weight[v]=weight;
v->setWeight(weight);
DEBUG(std::cerr<<v->getWeight()<<":Set weight------\n";
printGraph();
printEdge(Edge(u,v,weight)));
}
}
}
return st;
}
//print the graph (for debugging)
void Graph::printGraph(){
vector<Node *> lt=getAllNodes();
std::cerr<<"Graph---------------------\n";
for(vector<Node *>::iterator LI=lt.begin(), LE=lt.end(); LI!=LE; ++LI){
std::cerr<<((*LI)->getElement())->getName()<<"->";
Graph::nodeList &nl = getNodeList(*LI);
for(Graph::nodeList::iterator NI=nl.begin(), NE=nl.end(); NI!=NE; ++NI){
std::cerr<<":"<<"("<<(NI->element->getElement())
->getName()<<":"<<NI->element->getWeight()<<","<<NI->weight<<")";
}
std::cerr<<"--------\n";
}
}
//get a list of nodes in the graph
//in r-topological sorted order
//note that we assumed graph to be connected
vector<Node *> Graph::reverseTopologicalSort(){
vector <Node *> toReturn;
vector<Node *> lt=getAllNodes();
for(vector<Node *>::iterator LI=lt.begin(), LE=lt.end(); LI!=LE; ++LI){
if((*LI)->getWeight()!=GREY && (*LI)->getWeight()!=BLACK)
DFS_Visit(*LI, toReturn);
}
return toReturn;
}
//a private method for doing DFS traversal of graph
//this is used in determining the reverse topological sort
//of the graph
void Graph::DFS_Visit(Node *nd, vector<Node *> &toReturn){
nd->setWeight(GREY);
vector<Node *> lt=getSuccNodes(nd);
for(vector<Node *>::iterator LI=lt.begin(), LE=lt.end(); LI!=LE; ++LI){
if((*LI)->getWeight()!=GREY && (*LI)->getWeight()!=BLACK)
DFS_Visit(*LI, toReturn);
}
toReturn.push_back(nd);
}
//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 Graph::makeUnDirectional(){
vector<Node* > allNodes=getAllNodes();
for(vector<Node *>::iterator NI=allNodes.begin(), NE=allNodes.end(); NI!=NE;
++NI) {
nodeList &nl = getNodeList(*NI);
for(nodeList::iterator NLI=nl.begin(), NLE=nl.end(); NLI!=NLE; ++NLI){
Edge ed(NLI->element, *NI, NLI->weight);
if(!hasEdgeAndWt(ed)){
DEBUG(std::cerr<<"######doesn't hv\n";
printEdge(ed));
addEdgeForce(ed);
}
}
}
}
//reverse the sign of weights on edges
//this way, max-spanning tree could be obtained
//using min-spanning tree, and vice versa
void Graph::reverseWts(){
vector<Node *> allNodes=getAllNodes();
for(vector<Node *>::iterator NI=allNodes.begin(), NE=allNodes.end(); NI!=NE;
++NI) {
nodeList &node_list = getNodeList(*NI);
for(nodeList::iterator NLI=nodes[*NI].begin(), NLE=nodes[*NI].end();
NLI!=NLE; ++NLI)
NLI->weight=-NLI->weight;
}
}
//getting the backedges in a graph
//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 Graph::getBackEdges(vector<Edge > &be, std::map<Node *, int> &d){
std::map<Node *, Color > color;
int time=0;
getBackEdgesVisit(getRoot(), be, color, d, time);
}
//helper function to get back edges: it is called by
//the "getBackEdges" function above
void Graph::getBackEdgesVisit(Node *u, vector<Edge > &be,
std::map<Node *, Color > &color,
std::map<Node *, int > &d, int &time) {
color[u]=GREY;
time++;
d[u]=time;
vector<graphListElement> &succ_list = getNodeList(u);
for(vector<graphListElement>::iterator vl=succ_list.begin(),
ve=succ_list.end(); vl!=ve; ++vl){
Node *v=vl->element;
if(color[v]!=GREY && color[v]!=BLACK){
getBackEdgesVisit(v, be, color, d, time);
}
//now checking for d and f vals
if(color[v]==GREY){
//so v is ancestor of u if time of u > time of v
if(d[u] >= d[v]){
Edge *ed=new Edge(u, v,vl->weight, vl->randId);
if (!(*u == *getExit() && *v == *getRoot()))
be.push_back(*ed); // choose the forward edges
}
}
}
color[u]=BLACK;//done with visiting the node and its neighbors
}
} // End llvm namespace

View File

@ -1,480 +0,0 @@
//===-- 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

View File

@ -1,679 +0,0 @@
//===- GraphAuxiliary.cpp - Auxiliary functions on graph ------------------===//
//
// 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.
//
//===----------------------------------------------------------------------===//
//
// auxiliary function associated with graph: they all operate on graph, and help
// in inserting instrumentation for trace generation
//
//===----------------------------------------------------------------------===//
#include "llvm/Pass.h"
#include "llvm/Module.h"
#include "llvm/Instructions.h"
#include "llvm/Support/Debug.h"
#include <algorithm>
#include "Graph.h"
//using std::list;
using std::map;
using std::vector;
using std::cerr;
namespace llvm {
//check if 2 edges are equal (same endpoints and same weight)
static bool edgesEqual(Edge ed1, Edge ed2){
return ((ed1==ed2) && ed1.getWeight()==ed2.getWeight());
}
//Get the vector of edges that are to be instrumented in the graph
static void getChords(vector<Edge > &chords, Graph &g, Graph st){
//make sure the spanning tree is directional
//iterate over ALL the edges of the graph
vector<Node *> allNodes=g.getAllNodes();
for(vector<Node *>::iterator NI=allNodes.begin(), NE=allNodes.end(); NI!=NE;
++NI){
Graph::nodeList node_list=g.getNodeList(*NI);
for(Graph::nodeList::iterator NLI=node_list.begin(), NLE=node_list.end();
NLI!=NLE; ++NLI){
Edge f(*NI, NLI->element,NLI->weight, NLI->randId);
if(!(st.hasEdgeAndWt(f)))//addnl
chords.push_back(f);
}
}
}
//Given a tree t, and a "directed graph" g
//replace the edges in the tree t with edges that exist in graph
//The tree is formed from "undirectional" copy of graph
//So whatever edges the tree has, the undirectional graph
//would have too. This function corrects some of the directions in
//the tree so that now, all edge directions in the tree match
//the edge directions of corresponding edges in the directed graph
static void removeTreeEdges(Graph &g, Graph& t){
vector<Node* > allNodes=t.getAllNodes();
for(vector<Node *>::iterator NI=allNodes.begin(), NE=allNodes.end(); NI!=NE;
++NI){
Graph::nodeList nl=t.getNodeList(*NI);
for(Graph::nodeList::iterator NLI=nl.begin(), NLE=nl.end(); NLI!=NLE;++NLI){
Edge ed(NLI->element, *NI, NLI->weight);
if(!g.hasEdgeAndWt(ed)) t.removeEdge(ed);//tree has only one edge
//between any pair of vertices, so no need to delete by edge wt
}
}
}
//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, map<Node *, int> nodePriority,
vector<Edge> &be){
vector<Node *> revtop=g.reverseTopologicalSort();
map<Node *,int > NumPaths;
for(vector<Node *>::iterator RI=revtop.begin(), RE=revtop.end();
RI!=RE; ++RI){
if(g.isLeaf(*RI))
NumPaths[*RI]=1;
else{
NumPaths[*RI]=0;
// Modified Graph::nodeList &nlist=g.getNodeList(*RI);
Graph::nodeList &nlist=g.getSortedNodeList(*RI, be);
//sort nodelist by increasing order of numpaths
int sz=nlist.size();
for(int i=0;i<sz-1; i++){
int min=i;
for(int j=i+1; j<sz; j++){
BasicBlock *bb1 = nlist[j].element->getElement();
BasicBlock *bb2 = nlist[min].element->getElement();
if(bb1 == bb2) continue;
if(*RI == g.getRoot()){
assert(nodePriority[nlist[min].element]!=
nodePriority[nlist[j].element]
&& "priorities can't be same!");
if(nodePriority[nlist[j].element] <
nodePriority[nlist[min].element])
min = j;
}
else{
TerminatorInst *tti = (*RI)->getElement()->getTerminator();
BranchInst *ti = cast<BranchInst>(tti);
assert(ti && "not a branch");
assert(ti->getNumSuccessors()==2 && "less successors!");
BasicBlock *tB = ti->getSuccessor(0);
BasicBlock *fB = ti->getSuccessor(1);
if(tB == bb1 || fB == bb2)
min = j;
}
}
graphListElement tempEl=nlist[min];
nlist[min]=nlist[i];
nlist[i]=tempEl;
}
//sorted now!
for(Graph::nodeList::iterator GLI=nlist.begin(), GLE=nlist.end();
GLI!=GLE; ++GLI){
GLI->weight=NumPaths[*RI];
NumPaths[*RI]+=NumPaths[GLI->element];
}
}
}
return NumPaths[g.getRoot()];
}
//This is a helper function to get the edge increments
//This is used in conjunction with inc_DFS
//to get the edge increments
//Edge increment implies assigning 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
//inc_Dir tells whether 2 edges are in same, or in different directions
//if same direction, return 1, else -1
static int inc_Dir(Edge e, Edge f){
if(e.isNull())
return 1;
//check that the edges must have at least one common endpoint
assert(*(e.getFirst())==*(f.getFirst()) ||
*(e.getFirst())==*(f.getSecond()) ||
*(e.getSecond())==*(f.getFirst()) ||
*(e.getSecond())==*(f.getSecond()));
if(*(e.getFirst())==*(f.getSecond()) ||
*(e.getSecond())==*(f.getFirst()))
return 1;
return -1;
}
//used for getting edge increments (read comments above in inc_Dir)
//inc_DFS is a modification of DFS
static void inc_DFS(Graph& g,Graph& t,map<Edge, int, EdgeCompare2>& Increment,
int events, Node *v, Edge e){
vector<Node *> allNodes=t.getAllNodes();
for(vector<Node *>::iterator NI=allNodes.begin(), NE=allNodes.end(); NI!=NE;
++NI){
Graph::nodeList node_list=t.getNodeList(*NI);
for(Graph::nodeList::iterator NLI=node_list.begin(), NLE=node_list.end();
NLI!= NLE; ++NLI){
Edge f(*NI, NLI->element,NLI->weight, NLI->randId);
if(!edgesEqual(f,e) && *v==*(f.getSecond())){
int dir_count=inc_Dir(e,f);
int wt=1*f.getWeight();
inc_DFS(g,t, Increment, dir_count*events+wt, f.getFirst(), f);
}
}
}
for(vector<Node *>::iterator NI=allNodes.begin(), NE=allNodes.end(); NI!=NE;
++NI){
Graph::nodeList node_list=t.getNodeList(*NI);
for(Graph::nodeList::iterator NLI=node_list.begin(), NLE=node_list.end();
NLI!=NLE; ++NLI){
Edge f(*NI, NLI->element,NLI->weight, NLI->randId);
if(!edgesEqual(f,e) && *v==*(f.getFirst())){
int dir_count=inc_Dir(e,f);
int wt=f.getWeight();
inc_DFS(g,t, Increment, dir_count*events+wt,
f.getSecond(), f);
}
}
}
allNodes=g.getAllNodes();
for(vector<Node *>::iterator NI=allNodes.begin(), NE=allNodes.end(); NI!=NE;
++NI){
Graph::nodeList node_list=g.getNodeList(*NI);
for(Graph::nodeList::iterator NLI=node_list.begin(), NLE=node_list.end();
NLI!=NLE; ++NLI){
Edge f(*NI, NLI->element,NLI->weight, NLI->randId);
if(!(t.hasEdgeAndWt(f)) && (*v==*(f.getSecond()) ||
*v==*(f.getFirst()))){
int dir_count=inc_Dir(e,f);
Increment[f]+=dir_count*events;
}
}
}
}
//Now we select a subset of all edges
//and assign them some values such that
//if we consider just this subset, it still represents
//the path sum along any path in the graph
static map<Edge, int, EdgeCompare2> getEdgeIncrements(Graph& g, Graph& t,
vector<Edge> &be){
//get all edges in g-t
map<Edge, int, EdgeCompare2> Increment;
vector<Node *> allNodes=g.getAllNodes();
for(vector<Node *>::iterator NI=allNodes.begin(), NE=allNodes.end(); NI!=NE;
++NI){
Graph::nodeList node_list=g.getSortedNodeList(*NI, be);
//modified g.getNodeList(*NI);
for(Graph::nodeList::iterator NLI=node_list.begin(), NLE=node_list.end();
NLI!=NLE; ++NLI){
Edge ed(*NI, NLI->element,NLI->weight,NLI->randId);
if(!(t.hasEdgeAndWt(ed))){
Increment[ed]=0;;
}
}
}
Edge *ed=new Edge();
inc_DFS(g,t,Increment, 0, g.getRoot(), *ed);
for(vector<Node *>::iterator NI=allNodes.begin(), NE=allNodes.end(); NI!=NE;
++NI){
Graph::nodeList node_list=g.getSortedNodeList(*NI, be);
//modified g.getNodeList(*NI);
for(Graph::nodeList::iterator NLI=node_list.begin(), NLE=node_list.end();
NLI!=NLE; ++NLI){
Edge ed(*NI, NLI->element,NLI->weight, NLI->randId);
if(!(t.hasEdgeAndWt(ed))){
int wt=ed.getWeight();
Increment[ed]+=wt;
}
}
}
return Increment;
}
//push it up: TODO
const graphListElement *findNodeInList(const Graph::nodeList &NL,
Node *N);
graphListElement *findNodeInList(Graph::nodeList &NL, Node *N);
//end TODO
//Based on edgeIncrements (above), now obtain
//the kind of code to be inserted along an edge
//The idea here is to minimize the computation
//by inserting only the needed code
static void getCodeInsertions(Graph &g, map<Edge, getEdgeCode *, EdgeCompare2> &instr,
vector<Edge > &chords,
map<Edge,int, EdgeCompare2> &edIncrements){
//Register initialization code
vector<Node *> ws;
ws.push_back(g.getRoot());
while(ws.size()>0){
Node *v=ws.back();
ws.pop_back();
//for each edge v->w
Graph::nodeList succs=g.getNodeList(v);
for(Graph::nodeList::iterator nl=succs.begin(), ne=succs.end();
nl!=ne; ++nl){
int edgeWt=nl->weight;
Node *w=nl->element;
//if chords has v->w
Edge ed(v,w, edgeWt, nl->randId);
bool hasEdge=false;
for(vector<Edge>::iterator CI=chords.begin(), CE=chords.end();
CI!=CE && !hasEdge;++CI){
if(*CI==ed && CI->getWeight()==edgeWt){//modf
hasEdge=true;
}
}
if(hasEdge){//so its a chord edge
getEdgeCode *edCd=new getEdgeCode();
edCd->setCond(1);
edCd->setInc(edIncrements[ed]);
instr[ed]=edCd;
}
else if(g.getNumberOfIncomingEdges(w)==1){
ws.push_back(w);
}
else{
getEdgeCode *edCd=new getEdgeCode();
edCd->setCond(2);
edCd->setInc(0);
instr[ed]=edCd;
}
}
}
/////Memory increment code
ws.push_back(g.getExit());
while(!ws.empty()) {
Node *w=ws.back();
ws.pop_back();
///////
//vector<Node *> lt;
vector<Node *> lllt=g.getAllNodes();
for(vector<Node *>::iterator EII=lllt.begin(); EII!=lllt.end() ;++EII){
Node *lnode=*EII;
Graph::nodeList &nl = g.getNodeList(lnode);
//graphListElement *N = findNodeInList(nl, w);
for(Graph::nodeList::const_iterator N = nl.begin(),
NNEN = nl.end(); N!= NNEN; ++N){
if (*N->element == *w){
Node *v=lnode;
//if chords has v->w
Edge ed(v,w, N->weight, N->randId);
getEdgeCode *edCd=new getEdgeCode();
bool hasEdge=false;
for(vector<Edge>::iterator CI=chords.begin(), CE=chords.end(); CI!=CE;
++CI){
if(*CI==ed && CI->getWeight()==N->weight){
hasEdge=true;
break;
}
}
if(hasEdge){
//char str[100];
if(instr[ed]!=NULL && instr[ed]->getCond()==1){
instr[ed]->setCond(4);
}
else{
edCd->setCond(5);
edCd->setInc(edIncrements[ed]);
instr[ed]=edCd;
}
}
else if(g.getNumberOfOutgoingEdges(v)==1)
ws.push_back(v);
else{
edCd->setCond(6);
instr[ed]=edCd;
}
}
}
}
}
///// Register increment code
for(vector<Edge>::iterator CI=chords.begin(), CE=chords.end(); CI!=CE; ++CI){
getEdgeCode *edCd=new getEdgeCode();
if(instr[*CI]==NULL){
edCd->setCond(3);
edCd->setInc(edIncrements[*CI]);
instr[*CI]=edCd;
}
}
}
//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
//changed
void addDummyEdges(vector<Edge > &stDummy,
vector<Edge > &exDummy,
Graph &g, vector<Edge> &be){
for(vector<Edge >::iterator VI=be.begin(), VE=be.end(); VI!=VE; ++VI){
Edge ed=*VI;
Node *first=ed.getFirst();
Node *second=ed.getSecond();
g.removeEdge(ed);
if(!(*second==*(g.getRoot()))){
Edge *st=new Edge(g.getRoot(), second, ed.getWeight(), ed.getRandId());
stDummy.push_back(*st);
g.addEdgeForce(*st);
}
if(!(*first==*(g.getExit()))){
Edge *ex=new Edge(first, g.getExit(), ed.getWeight(), ed.getRandId());
exDummy.push_back(*ex);
g.addEdgeForce(*ex);
}
}
}
//print a given edge in the form BB1Label->BB2Label
void printEdge(Edge ed){
cerr<<((ed.getFirst())->getElement())
->getName()<<"->"<<((ed.getSecond())
->getElement())->getName()<<
":"<<ed.getWeight()<<" rndId::"<<ed.getRandId()<<"\n";
}
//Move the incoming dummy edge code and outgoing dummy
//edge code over to the corresponding back edge
static void moveDummyCode(vector<Edge> &stDummy,
vector<Edge> &exDummy,
vector<Edge> &be,
map<Edge, getEdgeCode *, EdgeCompare2> &insertions,
Graph &g){
typedef vector<Edge >::iterator vec_iter;
map<Edge,getEdgeCode *, EdgeCompare2> temp;
//iterate over edges with code
std::vector<Edge> toErase;
for(map<Edge,getEdgeCode *, EdgeCompare2>::iterator MI=insertions.begin(),
ME=insertions.end(); MI!=ME; ++MI){
Edge ed=MI->first;
getEdgeCode *edCd=MI->second;
///---new code
//iterate over be, and check if its starts and end vertices hv code
for(vector<Edge>::iterator BEI=be.begin(), BEE=be.end(); BEI!=BEE; ++BEI){
if(ed.getRandId()==BEI->getRandId()){
if(temp[*BEI]==0)
temp[*BEI]=new getEdgeCode();
//so ed is either in st, or ex!
if(ed.getFirst()==g.getRoot()){
//so its in stDummy
temp[*BEI]->setCdIn(edCd);
toErase.push_back(ed);
}
else if(ed.getSecond()==g.getExit()){
//so its in exDummy
toErase.push_back(ed);
temp[*BEI]->setCdOut(edCd);
}
else{
assert(false && "Not found in either start or end! Rand failed?");
}
}
}
}
for(vector<Edge >::iterator vmi=toErase.begin(), vme=toErase.end(); vmi!=vme;
++vmi){
insertions.erase(*vmi);
g.removeEdgeWithWt(*vmi);
}
for(map<Edge,getEdgeCode *, EdgeCompare2>::iterator MI=temp.begin(),
ME=temp.end(); MI!=ME; ++MI){
insertions[MI->first]=MI->second;
}
#ifdef DEBUG_PATH_PROFILES
cerr<<"size of deletions: "<<toErase.size()<<"\n";
cerr<<"SIZE OF INSERTIONS AFTER DEL "<<insertions.size()<<"\n";
#endif
}
//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,
vector<Edge >& be,
vector<Edge >& stDummy,
vector<Edge >& exDummy,
int numPaths, int MethNo,
Value *threshold){
//Given a graph: with exit->root edge, do the following in seq:
//1. get back edges
//2. insert dummy edges and remove back edges
//3. get edge assignments
//4. Get Max spanning tree of graph:
// -Make graph g2=g undirectional
// -Get Max spanning tree t
// -Make t undirectional
// -remove edges from t not in graph g
//5. Get edge increments
//6. Get code insertions
//7. move code on dummy edges over to the back edges
//This is used as maximum "weight" for
//priority queue
//This would hold all
//right as long as number of paths in the graph
//is less than this
const int Infinity=99999999;
//step 1-3 are already done on the graph when this function is called
DEBUG(printGraph(g));
//step 4: Get Max spanning tree of graph
//now insert exit to root edge
//if its there earlier, remove it!
//assign it weight Infinity
//so that this edge IS ALWAYS IN spanning tree
//Note than edges in spanning tree do not get
//instrumented: and we do not want the
//edge exit->root to get instrumented
//as it MAY BE a dummy edge
Edge ed(g.getExit(),g.getRoot(),Infinity);
g.addEdge(ed,Infinity);
Graph g2=g;
//make g2 undirectional: this gives a better
//maximal spanning tree
g2.makeUnDirectional();
DEBUG(printGraph(g2));
Graph *t=g2.getMaxSpanningTree();
#ifdef DEBUG_PATH_PROFILES
std::cerr<<"Original maxspanning tree\n";
printGraph(*t);
#endif
//now edges of tree t have weights reversed
//(negative) because the algorithm used
//to find max spanning tree is
//actually for finding min spanning tree
//so get back the original weights
t->reverseWts();
//Ordinarily, the graph is directional
//lets converts the graph into an
//undirectional graph
//This is done by adding an edge
//v->u for all existing edges u->v
t->makeUnDirectional();
//Given a tree t, and a "directed graph" g
//replace the edges in the tree t with edges that exist in graph
//The tree is formed from "undirectional" copy of graph
//So whatever edges the tree has, the undirectional graph
//would have too. This function corrects some of the directions in
//the tree so that now, all edge directions in the tree match
//the edge directions of corresponding edges in the directed graph
removeTreeEdges(g, *t);
#ifdef DEBUG_PATH_PROFILES
cerr<<"Final Spanning tree---------\n";
printGraph(*t);
cerr<<"-------end spanning tree\n";
#endif
//now remove the exit->root node
//and re-add it with weight 0
//since infinite weight is kinda confusing
g.removeEdge(ed);
Edge edNew(g.getExit(), g.getRoot(),0);
g.addEdge(edNew,0);
if(t->hasEdge(ed)){
t->removeEdge(ed);
t->addEdge(edNew,0);
}
DEBUG(printGraph(g);
printGraph(*t));
//step 5: Get edge increments
//Now we select a subset of all edges
//and assign them some values such that
//if we consider just this subset, it still represents
//the path sum along any path in the graph
map<Edge, int, EdgeCompare2> increment=getEdgeIncrements(g,*t, be);
#ifdef DEBUG_PATH_PROFILES
//print edge increments for debugging
std::cerr<<"Edge Increments------\n";
for(map<Edge, int, EdgeCompare2>::iterator MMI=increment.begin(), MME=increment.end(); MMI != MME; ++MMI){
printEdge(MMI->first);
std::cerr<<"Increment for above:"<<MMI->second<<"\n";
}
std::cerr<<"-------end of edge increments\n";
#endif
//step 6: Get code insertions
//Based on edgeIncrements (above), now obtain
//the kind of code to be inserted along an edge
//The idea here is to minimize the computation
//by inserting only the needed code
vector<Edge> chords;
getChords(chords, g, *t);
map<Edge, getEdgeCode *, EdgeCompare2> codeInsertions;
getCodeInsertions(g, codeInsertions, chords,increment);
#ifdef DEBUG_PATH_PROFILES
//print edges with code for debugging
cerr<<"Code inserted in following---------------\n";
for(map<Edge, getEdgeCode *, EdgeCompare2>::iterator cd_i=codeInsertions.begin(),
cd_e=codeInsertions.end(); cd_i!=cd_e; ++cd_i){
printEdge(cd_i->first);
cerr<<cd_i->second->getCond()<<":"<<cd_i->second->getInc()<<"\n";
}
cerr<<"-----end insertions\n";
#endif
//step 7: move code on dummy edges over to the back edges
//Move the incoming dummy edge code and outgoing dummy
//edge code over to the corresponding back edge
moveDummyCode(stDummy, exDummy, be, codeInsertions, g);
#ifdef DEBUG_PATH_PROFILES
//debugging info
cerr<<"After moving dummy code\n";
for(map<Edge, getEdgeCode *,EdgeCompare2>::iterator cd_i=codeInsertions.begin(),
cd_e=codeInsertions.end(); cd_i != cd_e; ++cd_i){
printEdge(cd_i->first);
cerr<<cd_i->second->getCond()<<":"
<<cd_i->second->getInc()<<"\n";
}
cerr<<"Dummy end------------\n";
#endif
//see what it looks like...
//now insert code along edges which have codes on them
for(map<Edge, getEdgeCode *,EdgeCompare2>::iterator MI=codeInsertions.begin(),
ME=codeInsertions.end(); MI!=ME; ++MI){
Edge ed=MI->first;
insertBB(ed, MI->second, rInst, countInst, numPaths, MethNo, threshold);
}
}
//print the graph (for debugging)
void printGraph(Graph &g){
vector<Node *> lt=g.getAllNodes();
cerr<<"Graph---------------------\n";
for(vector<Node *>::iterator LI=lt.begin();
LI!=lt.end(); ++LI){
cerr<<((*LI)->getElement())->getName()<<"->";
Graph::nodeList nl=g.getNodeList(*LI);
for(Graph::nodeList::iterator NI=nl.begin();
NI!=nl.end(); ++NI){
cerr<<":"<<"("<<(NI->element->getElement())
->getName()<<":"<<NI->element->getWeight()<<","<<NI->weight<<","
<<NI->randId<<")";
}
cerr<<"\n";
}
cerr<<"--------------------Graph\n";
}
} // End llvm namespace

View File

@ -1,185 +0,0 @@
//===-- InstLoops.cpp -----------------------------------------------------===//
//
// 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.
//
//===----------------------------------------------------------------------===//
//
// This is the first-level instrumentation pass for the Reoptimizer. It
// instrument the back-edges of loops by inserting a basic block
// containing a call to llvm_first_trigger (the first-level trigger function),
// and inserts an initialization call to the main() function.
//
//===----------------------------------------------------------------------===//
#include "llvm/Analysis/Dominators.h"
#include "llvm/Support/CFG.h"
#include "llvm/Instructions.h"
#include "llvm/Module.h"
#include "llvm/Pass.h"
#include "llvm/Type.h"
#include "llvm/Support/Debug.h"
#include "llvm/Transforms/Instrumentation.h"
#include "../ProfilingUtils.h"
namespace llvm {
//this is used to color vertices
//during DFS
enum Color{
WHITE,
GREY,
BLACK
};
namespace {
typedef std::map<BasicBlock *, BasicBlock *> BBMap;
struct InstLoops : public FunctionPass {
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
AU.addRequired<DominatorSet>();
}
private:
Function *inCountMth;
DominatorSet *DS;
void getBackEdgesVisit(BasicBlock *u,
std::map<BasicBlock *, Color > &color,
std::map<BasicBlock *, int > &d,
int &time, BBMap &be);
void removeRedundant(BBMap &be);
void findAndInstrumentBackEdges(Function &F);
public:
bool doInitialization(Module &M);
bool runOnFunction(Function &F);
};
RegisterOpt<InstLoops> X("instloops", "Instrument backedges for profiling");
}
//helper function to get back edges: it is called by
//the "getBackEdges" function below
void InstLoops::getBackEdgesVisit(BasicBlock *u,
std::map<BasicBlock *, Color > &color,
std::map<BasicBlock *, int > &d,
int &time, BBMap &be) {
color[u]=GREY;
time++;
d[u]=time;
for(succ_iterator vl = succ_begin(u), ve = succ_end(u); vl != ve; ++vl){
BasicBlock *BB = *vl;
if(color[BB]!=GREY && color[BB]!=BLACK){
getBackEdgesVisit(BB, color, d, time, be);
}
//now checking for d and f vals
else if(color[BB]==GREY){
//so v is ancestor of u if time of u > time of v
if(d[u] >= d[BB]){
//u->BB is a backedge
be[u] = BB;
}
}
}
color[u]=BLACK;//done with visiting the node and its neighbors
}
//look at all BEs, and remove all BEs that are dominated by other BE's in the
//set
void InstLoops::removeRedundant(BBMap &be) {
std::vector<BasicBlock *> toDelete;
for(std::map<BasicBlock *, BasicBlock *>::iterator MI = be.begin(),
ME = be.end(); MI != ME; ++MI)
for(BBMap::iterator MMI = be.begin(), MME = be.end(); MMI != MME; ++MMI)
if(DS->properlyDominates(MI->first, MMI->first))
toDelete.push_back(MMI->first);
// Remove all the back-edges we found from be.
for(std::vector<BasicBlock *>::iterator VI = toDelete.begin(),
VE = toDelete.end(); VI != VE; ++VI)
be.erase(*VI);
}
//getting the backedges in a graph
//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 InstLoops::findAndInstrumentBackEdges(Function &F){
std::map<BasicBlock *, Color > color;
std::map<BasicBlock *, int> d;
BBMap be;
int time=0;
getBackEdgesVisit(F.begin(), color, d, time, be);
removeRedundant(be);
for(std::map<BasicBlock *, BasicBlock *>::iterator MI = be.begin(),
ME = be.end(); MI != ME; ++MI){
BasicBlock *u = MI->first;
BasicBlock *BB = MI->second;
// We have a back-edge from BB --> u.
DEBUG (std::cerr << "Instrumenting back-edge from " << BB->getName ()
<< "-->" << u->getName () << "\n");
// Split the back-edge, inserting a new basic block on it, and modify the
// source BB's terminator accordingly.
BasicBlock *newBB = new BasicBlock("backEdgeInst", u->getParent());
BranchInst *ti = cast<BranchInst>(u->getTerminator());
unsigned char index = ((ti->getSuccessor(0) == BB) ? 0 : 1);
assert(ti->getNumSuccessors() > index && "Not enough successors!");
ti->setSuccessor(index, newBB);
BasicBlock::InstListType &lt = newBB->getInstList();
lt.push_back(new CallInst(inCountMth));
new BranchInst(BB, newBB);
// Now, set the sources of Phi nodes corresponding to the back-edge
// in BB to come from the instrumentation block instead.
for(BasicBlock::iterator BB2Inst = BB->begin(), BBend = BB->end();
BB2Inst != BBend; ++BB2Inst) {
if (PHINode *phiInst = dyn_cast<PHINode>(BB2Inst)) {
int bbIndex = phiInst->getBasicBlockIndex(u);
if (bbIndex>=0)
phiInst->setIncomingBlock(bbIndex, newBB);
}
}
}
}
bool InstLoops::doInitialization (Module &M) {
inCountMth = M.getOrInsertFunction("llvm_first_trigger", Type::VoidTy,
(Type *)0);
return true; // Module was modified.
}
/// runOnFunction - Entry point for FunctionPass that inserts calls to
/// trigger function.
///
bool InstLoops::runOnFunction(Function &F){
if (F.isExternal ())
return false;
DS = &getAnalysis<DominatorSet> ();
// Add a call to reoptimizerInitialize() to beginning of function named main.
if (F.getName() == "main")
InsertProfilingInitCall (&F, "reoptimizerInitialize");
findAndInstrumentBackEdges(F);
return true; // Function was modified.
}
FunctionPass *createLoopInstrumentationPass () {
return new InstLoops();
}
} // End llvm namespace

View File

@ -1,13 +0,0 @@
##===- lib/Transforms/Instrumentation/ProfilePaths/Makefile -*- Makefile -*-===##
#
# 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.
#
##===----------------------------------------------------------------------===##
LEVEL = ../../../..
LIBRARYNAME = LLVMProfilePaths
include $(LEVEL)/Makefile.common

View File

@ -1,252 +0,0 @@
//===-- ProfilePaths.cpp - interface to insert instrumentation --*- 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.
//
//===----------------------------------------------------------------------===//
//
// This inserts instrumentation for counting execution of paths though a given
// function Its implemented as a "Function" Pass, and called using opt
//
// This pass is implemented by using algorithms similar to
// 1."Efficient Path Profiling": Ball, T. and Larus, J. R.,
// Proceedings of Micro-29, Dec 1996, Paris, France.
// 2."Efficiently Counting Program events with support for on-line
// "queries": Ball T., ACM Transactions on Programming Languages
// and systems, Sep 1994.
//
// The algorithms work on a Graph constructed over the nodes made from Basic
// Blocks: The transformations then take place on the constructed graph
// (implementation in Graph.cpp and GraphAuxiliary.cpp) and finally, appropriate
// instrumentation is placed over suitable edges. (code inserted through
// EdgeCode.cpp).
//
// The algorithm inserts code such that every acyclic path in the CFG of a
// function is identified through a unique number. the code insertion is optimal
// in the sense that its inserted over a minimal set of edges. Also, the
// algorithm makes sure than initialization, path increment and counter update
// can be collapsed into minimum number of edges.
//
//===----------------------------------------------------------------------===//
#include "llvm/Transforms/Instrumentation.h"
#include "llvm/Transforms/Utils/UnifyFunctionExitNodes.h"
#include "llvm/Support/CFG.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Instructions.h"
#include "llvm/Module.h"
#include "Graph.h"
#include <fstream>
#include <cstdio>
namespace llvm {
struct ProfilePaths : public FunctionPass {
bool runOnFunction(Function &F);
// Before this pass, make sure that there is only one
// entry and only one exit node for the function in the CFG of the function
//
void getAnalysisUsage(AnalysisUsage &AU) const {
AU.addRequired<UnifyFunctionExitNodes>();
}
};
static RegisterOpt<ProfilePaths> X("paths", "Profile Paths");
FunctionPass *createProfilePathsPass() { return new ProfilePaths(); }
static Node *findBB(std::vector<Node *> &st, BasicBlock *BB){
for(std::vector<Node *>::iterator si=st.begin(); si!=st.end(); ++si){
if(((*si)->getElement())==BB){
return *si;
}
}
return NULL;
}
//Per function pass for inserting counters and trigger code
bool ProfilePaths::runOnFunction(Function &F){
static int mn = -1;
static int CountCounter = 1;
if(F.isExternal()) {
return false;
}
//increment counter for instrumented functions. mn is now function#
mn++;
// Transform the cfg s.t. we have just one exit node
BasicBlock *ExitNode =
getAnalysis<UnifyFunctionExitNodes>().getReturnBlock();
//iterating over BBs and making graph
std::vector<Node *> nodes;
std::vector<Edge> edges;
Node *exitNode = 0, *startNode = 0;
// The nodes must be uniquely identified:
// That is, no two nodes must hav same BB*
for (Function::iterator BB = F.begin(), BE = F.end(); BB != BE; ++BB) {
Node *nd=new Node(BB);
nodes.push_back(nd);
if(&*BB == ExitNode)
exitNode=nd;
if(BB==F.begin())
startNode=nd;
}
// now do it again to insert edges
for (Function::iterator BB = F.begin(), BE = F.end(); BB != BE; ++BB){
Node *nd=findBB(nodes, BB);
assert(nd && "No node for this edge!");
for(succ_iterator s=succ_begin(BB), se=succ_end(BB); s!=se; ++s){
Node *nd2=findBB(nodes,*s);
assert(nd2 && "No node for this edge!");
Edge ed(nd,nd2,0);
edges.push_back(ed);
}
}
Graph g(nodes,edges, startNode, exitNode);
#ifdef DEBUG_PATH_PROFILES
std::cerr<<"Original graph\n";
printGraph(g);
#endif
BasicBlock *fr = &F.front();
// The graph is made acyclic: this is done
// by removing back edges for now, and adding them later on
std::vector<Edge> be;
std::map<Node *, int> nodePriority; //it ranks nodes in depth first order traversal
g.getBackEdges(be, nodePriority);
#ifdef DEBUG_PATH_PROFILES
std::cerr<<"BackEdges-------------\n";
for (std::vector<Edge>::iterator VI=be.begin(); VI!=be.end(); ++VI){
printEdge(*VI);
cerr<<"\n";
}
std::cerr<<"------\n";
#endif
#ifdef DEBUG_PATH_PROFILES
cerr<<"Backedges:"<<be.size()<<endl;
#endif
//Now we need to reflect the effect of back edges
//This is done by adding dummy edges
//If a->b is a back edge
//Then we add 2 back edges for it:
//1. from root->b (in vector stDummy)
//and 2. from a->exit (in vector exDummy)
std::vector<Edge> stDummy;
std::vector<Edge> exDummy;
addDummyEdges(stDummy, exDummy, g, be);
#ifdef DEBUG_PATH_PROFILES
std::cerr<<"After adding dummy edges\n";
printGraph(g);
#endif
// Now, every edge in the graph is assigned a weight
// This weight later adds on to assign path
// numbers to different paths in the graph
// All paths for now are acyclic,
// since no back edges in the graph now
// numPaths is the number of acyclic paths in the graph
int numPaths=valueAssignmentToEdges(g, nodePriority, be);
//if(numPaths<=1) return false;
static GlobalVariable *threshold = NULL;
static bool insertedThreshold = false;
if(!insertedThreshold){
threshold = new GlobalVariable(Type::IntTy, false,
GlobalValue::ExternalLinkage, 0,
"reopt_threshold");
F.getParent()->getGlobalList().push_back(threshold);
insertedThreshold = true;
}
assert(threshold && "GlobalVariable threshold not defined!");
if(fr->getParent()->getName() == "main"){
//initialize threshold
// FIXME: THIS IS HORRIBLY BROKEN. FUNCTION PASSES CANNOT DO THIS, EXCEPT
// IN THEIR INITIALIZE METHOD!!
Function *initialize =
F.getParent()->getOrInsertFunction("reoptimizerInitialize", Type::VoidTy,
PointerType::get(Type::IntTy),
(Type *)0);
std::vector<Value *> trargs;
trargs.push_back(threshold);
new CallInst(initialize, trargs, "", fr->begin());
}
if(numPaths<=1 || numPaths >5000) return false;
#ifdef DEBUG_PATH_PROFILES
printGraph(g);
#endif
//create instruction allocation r and count
//r is the variable that'll act like an accumulator
//all along the path, we just add edge values to r
//and at the end, r reflects the path number
//count is an array: count[x] would store
//the number of executions of path numbered x
Instruction *rVar=new
AllocaInst(Type::IntTy,
ConstantUInt::get(Type::UIntTy,1),"R");
//Instruction *countVar=new
//AllocaInst(Type::IntTy,
// ConstantUInt::get(Type::UIntTy, numPaths), "Count");
//initialize counter array!
std::vector<Constant*> arrayInitialize;
for(int xi=0; xi<numPaths; xi++)
arrayInitialize.push_back(ConstantSInt::get(Type::IntTy, 0));
const ArrayType *ATy = ArrayType::get(Type::IntTy, numPaths);
Constant *initializer = ConstantArray::get(ATy, arrayInitialize);
char tempChar[20];
sprintf(tempChar, "Count%d", CountCounter);
CountCounter++;
std::string countStr = tempChar;
GlobalVariable *countVar = new GlobalVariable(ATy, false,
GlobalValue::InternalLinkage,
initializer, countStr,
F.getParent());
// insert initialization code in first (entry) BB
// this includes initializing r and count
insertInTopBB(&F.getEntryBlock(), numPaths, rVar, threshold);
//now process the graph: get path numbers,
//get increments along different paths,
//and assign "increments" and "updates" (to r and count)
//"optimally". Finally, insert llvm code along various edges
processGraph(g, rVar, countVar, be, stDummy, exDummy, numPaths, mn,
threshold);
return true; // Always modifies function
}
} // End llvm namespace

View File

@ -1,308 +0,0 @@
//===- RetracePath.cpp ----------------------------------------------------===//
//
// 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.
//
//===----------------------------------------------------------------------===//
//
// Retraces a path of BasicBlock, given a path number and a graph!
//
//===----------------------------------------------------------------------===//
#include "llvm/Module.h"
#include "llvm/Instructions.h"
#include "llvm/Support/CFG.h"
#include "Graph.h"
#include <iostream>
using std::vector;
using std::map;
using std::cerr;
namespace llvm {
//Routines to get the path trace!
void getPathFrmNode(Node *n, vector<BasicBlock*> &vBB, int pathNo, Graph &g,
vector<Edge> &stDummy, vector<Edge> &exDummy,
vector<Edge> &be,
double strand){
Graph::nodeList &nlist = g.getNodeList(n);
//printGraph(g);
//std::cerr<<"Path No: "<<pathNo<<"\n";
int maxCount=-9999999;
bool isStart=false;
if(*n==*g.getRoot())//its root: so first node of path
isStart=true;
double edgeRnd=0;
Node *nextRoot=n;
for(Graph::nodeList::iterator NLI = nlist.begin(), NLE=nlist.end(); NLI!=NLE;
++NLI){
if(NLI->weight>maxCount && NLI->weight<=pathNo){
maxCount=NLI->weight;
nextRoot=NLI->element;
edgeRnd=NLI->randId;
if(isStart)
strand=NLI->randId;
}
}
if(!isStart)
assert(strand!=-1 && "strand not assigned!");
assert(!(*nextRoot==*n && pathNo>0) && "No more BBs to go");
assert(!(*nextRoot==*g.getExit() && pathNo-maxCount!=0) && "Reached exit");
vBB.push_back(n->getElement());
if(pathNo-maxCount==0 && *nextRoot==*g.getExit()){
//look for strnd and edgeRnd now:
bool has1=false, has2=false;
//check if exit has it
for(vector<Edge>::iterator VI=exDummy.begin(), VE=exDummy.end(); VI!=VE;
++VI){
if(VI->getRandId()==edgeRnd){
has2=true;
break;
}
}
//check if start has it
for(vector<Edge>::iterator VI=stDummy.begin(), VE=stDummy.end(); VI!=VE;
++VI){
if(VI->getRandId()==strand){
has1=true;
break;
}
}
if(has1){
//find backedge with endpoint vBB[1]
for(vector<Edge>::iterator VI=be.begin(), VE=be.end(); VI!=VE; ++VI){
assert(vBB.size()>0 && "vector too small");
if( VI->getSecond()->getElement() == vBB[1] ){
//vBB[0]=VI->getFirst()->getElement();
vBB.erase(vBB.begin());
break;
}
}
}
if(has2){
//find backedge with startpoint vBB[vBB.size()-1]
for(vector<Edge>::iterator VI=be.begin(), VE=be.end(); VI!=VE; ++VI){
assert(vBB.size()>0 && "vector too small");
if( VI->getFirst()->getElement() == vBB[vBB.size()-1] &&
VI->getSecond()->getElement() == vBB[0]){
//vBB.push_back(VI->getSecond()->getElement());
break;
}
}
}
else
vBB.push_back(nextRoot->getElement());
return;
}
assert(pathNo-maxCount>=0);
return getPathFrmNode(nextRoot, vBB, pathNo-maxCount, g, stDummy,
exDummy, be, strand);
}
static Node *findBB(std::vector<Node *> &st, BasicBlock *BB){
for(std::vector<Node *>::iterator si=st.begin(); si!=st.end(); ++si){
if(((*si)->getElement())==BB){
return *si;
}
}
return NULL;
}
void getBBtrace(vector<BasicBlock *> &vBB, int pathNo, Function *M){//,
// vector<Instruction *> &instToErase){
//step 1: create graph
//Transform the cfg s.t. we have just one exit node
std::vector<Node *> nodes;
std::vector<Edge> edges;
Node *exitNode=0, *startNode=0;
//Creat cfg just once for each function!
static std::map<Function *, Graph *> graphMap;
//get backedges, exit and start edges for the graphs and store them
static std::map<Function *, vector<Edge> > stMap, exMap, beMap;
static std::map<Function *, Value *> pathReg; //path register
if(!graphMap[M]){
BasicBlock *ExitNode = 0;
for (Function::iterator I = M->begin(), E = M->end(); I != E; ++I){
if (isa<ReturnInst>(I->getTerminator())) {
ExitNode = I;
break;
}
}
assert(ExitNode!=0 && "exitnode not found");
//iterating over BBs and making graph
//The nodes must be uniquely identified:
//That is, no two nodes must hav same BB*
//keep a map for trigger basicblocks!
std::map<BasicBlock *, unsigned char> triggerBBs;
//First enter just nodes: later enter edges
for(Function::iterator BB = M->begin(), BE=M->end(); BB != BE; ++BB){
bool cont = false;
if(BB->size()==3 || BB->size() ==2){
for(BasicBlock::iterator II = BB->begin(), IE = BB->end();
II != IE; ++II){
if(CallInst *callInst = dyn_cast<CallInst>(II)){
//std::cerr<<*callInst;
Function *calledFunction = callInst->getCalledFunction();
if(calledFunction && calledFunction->getName() == "trigger"){
triggerBBs[BB] = 9;
cont = true;
//std::cerr<<"Found trigger!\n";
break;
}
}
}
}
if(cont)
continue;
// const Instruction *inst = BB->getInstList().begin();
// if(isa<CallInst>(inst)){
// Instruction *ii1 = BB->getInstList().begin();
// CallInst *callInst = dyn_cast<CallInst>(ii1);
// if(callInst->getCalledFunction()->getName()=="trigger")
// continue;
// }
Node *nd=new Node(BB);
nodes.push_back(nd);
if(&*BB==ExitNode)
exitNode=nd;
if(&*BB==&M->front())
startNode=nd;
}
assert(exitNode!=0 && startNode!=0 && "Start or exit not found!");
for (Function::iterator BB = M->begin(), BE=M->end(); BB != BE; ++BB){
if(triggerBBs[BB] == 9)
continue;
//if(BB->size()==3)
//if(CallInst *callInst = dyn_cast<CallInst>(BB->getInstList().begin()))
//if(callInst->getCalledFunction()->getName() == "trigger")
//continue;
// if(BB->size()==2){
// const Instruction *inst = BB->getInstList().begin();
// if(isa<CallInst>(inst)){
// Instruction *ii1 = BB->getInstList().begin();
// CallInst *callInst = dyn_cast<CallInst>(ii1);
// if(callInst->getCalledFunction()->getName()=="trigger")
// continue;
// }
// }
Node *nd=findBB(nodes, BB);
assert(nd && "No node for this edge!");
for(succ_iterator s=succ_begin(BB), se=succ_end(BB); s!=se; ++s){
if(triggerBBs[*s] == 9){
//if(!pathReg[M]){ //Get the path register for this!
//if(BB->size()>8)
// if(LoadInst *ldInst = dyn_cast<LoadInst>(BB->getInstList().begin()))
// pathReg[M] = ldInst->getPointerOperand();
//}
continue;
}
//if((*s)->size()==3)
//if(CallInst *callInst =
// dyn_cast<CallInst>((*s)->getInstList().begin()))
// if(callInst->getCalledFunction()->getName() == "trigger")
// continue;
// if((*s)->size()==2){
// const Instruction *inst = (*s)->getInstList().begin();
// if(isa<CallInst>(inst)){
// Instruction *ii1 = (*s)->getInstList().begin();
// CallInst *callInst = dyn_cast<CallInst>(ii1);
// if(callInst->getCalledFunction()->getName()=="trigger")
// continue;
// }
// }
Node *nd2 = findBB(nodes,*s);
assert(nd2 && "No node for this edge!");
Edge ed(nd,nd2,0);
edges.push_back(ed);
}
}
graphMap[M]= new Graph(nodes,edges, startNode, exitNode);
Graph *g = graphMap[M];
if (M->size() <= 1) return; //uninstrumented
//step 2: getBackEdges
//vector<Edge> be;
std::map<Node *, int> nodePriority;
g->getBackEdges(beMap[M], nodePriority);
//step 3: add dummy edges
//vector<Edge> stDummy;
//vector<Edge> exDummy;
addDummyEdges(stMap[M], exMap[M], *g, beMap[M]);
//step 4: value assgn to edges
int numPaths = valueAssignmentToEdges(*g, nodePriority, beMap[M]);
}
//step 5: now travel from root, select max(edge) < pathNo,
//and go on until reach the exit
getPathFrmNode(graphMap[M]->getRoot(), vBB, pathNo, *graphMap[M],
stMap[M], exMap[M], beMap[M], -1);
//post process vBB to locate instructions to be erased
/*
if(pathReg[M]){
for(vector<BasicBlock *>::iterator VBI = vBB.begin(), VBE = vBB.end();
VBI != VBE; ++VBI){
for(BasicBlock::iterator BBI = (*VBI)->begin(), BBE = (*VBI)->end();
BBI != BBE; ++BBI){
if(LoadInst *ldInst = dyn_cast<LoadInst>(BBI)){
if(pathReg[M] == ldInst->getPointerOperand())
instToErase.push_back(ldInst);
}
else if(StoreInst *stInst = dyn_cast<StoreInst>(BBI)){
if(pathReg[M] == stInst->getPointerOperand())
instToErase.push_back(stInst);
}
}
}
}
*/
}
} // End llvm namespace