MEGAPATCH checkin.
[oota-llvm.git] / lib / Transforms / Instrumentation / ProfilePaths / EdgeCode.cpp
1 //===-- EdgeCode.cpp - generate LLVM instrumentation code --------*- C++ -*--=//
2 //It implements the class EdgeCode: which provides 
3 //support for inserting "appropriate" instrumentation at
4 //designated points in the graph
5 //
6 //It also has methods to insert initialization code in 
7 //top block of cfg
8 //===----------------------------------------------------------------------===//
9
10 #include "Graph.h"
11 #include "llvm/BasicBlock.h"
12 #include "llvm/Constants.h"
13 #include "llvm/DerivedTypes.h"
14 #include "llvm/iMemory.h"
15 #include "llvm/iTerminators.h"
16 #include "llvm/iOther.h"
17 #include "llvm/iOperators.h"
18 #include "llvm/iPHINode.h"
19
20 using std::vector;
21
22 //get the code to be inserted on the edge
23 //This is determined from cond (1-6)
24 void getEdgeCode::getCode(Instruction *rInst, 
25                           Instruction *countInst, 
26                           Function *M, 
27                           BasicBlock *BB){
28   
29   BasicBlock::InstListType& instList=BB->getInstList();
30   BasicBlock::iterator here=instList.begin();
31   
32   //case: r=k code to be inserted
33   switch(cond){
34   case 1:{
35     Value *val=ConstantSInt::get(Type::IntTy,inc);
36     Instruction *stInst=new StoreInst(val, rInst);
37     here=++instList.insert(here,stInst);
38     break;
39     }
40
41   //case: r=0 to be inserted
42   case 2:{
43     Value *val=ConstantSInt::get(Type::IntTy,0);
44     Instruction *stInst=new StoreInst(val, rInst);
45     here=++instList.insert(here,stInst);
46     break;
47   }
48     
49   //r+=k
50   case 3:{
51     Instruction *ldInst=new LoadInst(rInst, "ti1");
52     Value *val=ConstantSInt::get(Type::IntTy,inc);
53     Instruction *addIn=BinaryOperator::
54       create(Instruction::Add, ldInst, val,"ti2");
55     
56     Instruction *stInst=new StoreInst(addIn, rInst);
57     here=++instList.insert(here,ldInst);
58     here=++instList.insert(here,addIn);
59     here=++instList.insert(here,stInst);
60     break;
61   }
62
63   //count[inc]++
64   case 4:{
65     Instruction *ldInst=new 
66       LoadInst(countInst,vector<Value *>
67                (1,ConstantUInt::get(Type::UIntTy, inc)), "ti1");
68     Value *val=ConstantSInt::get(Type::IntTy,1);
69     Instruction *addIn=BinaryOperator::
70       create(Instruction::Add, ldInst, val,"ti2");
71
72     assert(inc>=0 && "IT MUST BE POSITIVE NOW");
73     Instruction *stInst=new 
74       StoreInst(addIn, countInst, vector<Value *>
75                 (1, ConstantUInt::get(Type::UIntTy,inc)));
76     
77     here=++instList.insert(here,ldInst);
78     here=++instList.insert(here,addIn);
79     here=++instList.insert(here,stInst);
80     break;
81   }
82
83   //case: count[r+inc]++
84   case 5:{
85     //ti1=inc+r
86     Instruction *ldIndex=new LoadInst(rInst, "ti1");
87     Value *val=ConstantSInt::get(Type::IntTy,inc);
88     Instruction *addIndex=BinaryOperator::
89       create(Instruction::Add, ldIndex, val,"ti2");
90     
91     //now load count[addIndex]
92     Instruction *castInst=new CastInst(addIndex, 
93                                        Type::UIntTy,"ctin");
94     Instruction *ldInst=new 
95       LoadInst(countInst, vector<Value *>(1,castInst), "ti3");
96     Value *cons=ConstantSInt::get(Type::IntTy,1);
97     
98     //count[addIndex]++
99     Instruction *addIn=BinaryOperator::
100       create(Instruction::Add, ldInst, cons,"ti4");
101     Instruction *stInst=new 
102       StoreInst(addIn, countInst, 
103                 vector<Value *>(1,castInst));
104     
105     here=++instList.insert(here,ldIndex);
106     here=++instList.insert(here,addIndex);
107     here=++instList.insert(here,castInst);
108     here=++instList.insert(here,ldInst);
109     here=++instList.insert(here,addIn);
110     here=++instList.insert(here,stInst);
111     break;
112   }
113
114     //case: count[r]+
115   case 6:{
116     //ti1=inc+r
117     Instruction *ldIndex=new LoadInst(rInst, "ti1");
118
119     //now load count[addIndex]
120     Instruction *castInst2=new 
121       CastInst(ldIndex, Type::UIntTy,"ctin");
122     Instruction *ldInst=new 
123       LoadInst(countInst, vector<Value *>(1,castInst2), "ti2");
124     Value *cons=ConstantSInt::get(Type::IntTy,1);
125
126     //count[addIndex]++
127     Instruction *addIn=BinaryOperator::
128       create(Instruction::Add, ldInst, cons,"ti3"); 
129     Instruction *stInst=new 
130       StoreInst(addIn, countInst, vector<Value *>(1,castInst2));
131     
132     here=++instList.insert(here,ldIndex);
133     here=++instList.insert(here,castInst2);
134     here=++instList.insert(here,ldInst);
135     here=++instList.insert(here,addIn);
136     here=++instList.insert(here,stInst);
137     break;
138   }
139     
140   }
141   //now check for cdIn and cdOut
142   //first put cdOut
143   if(cdOut!=NULL){
144     cdOut->getCode(rInst, countInst, M, BB);
145   }
146   if(cdIn!=NULL){
147     cdIn->getCode(rInst, countInst, M, BB);
148   }
149
150 }
151
152
153
154 //Insert the initialization code in the top BB
155 //this includes initializing r, and count
156 //r is like an accumulator, that 
157 //keeps on adding increments as we traverse along a path
158 //and at the end of the path, r contains the path
159 //number of that path
160 //Count is an array, where Count[k] represents
161 //the number of executions of path k
162 void insertInTopBB(BasicBlock *front, 
163                    int k, 
164                    Instruction *rVar, 
165                    Instruction *countVar){
166   //rVar is variable r, 
167   //countVar is array Count, and these are allocatted outside
168   
169   //store uint 0, uint *%R, uint 0
170   vector<Value *> idx;
171   idx.push_back(ConstantUInt::get(Type::UIntTy, 0));
172   Instruction *stInstr=new StoreInst(ConstantInt::get(Type::IntTy, 0), rVar, 
173                                      idx);
174
175   //now push all instructions in front of the BB
176   BasicBlock::InstListType& instList=front->getInstList();
177   BasicBlock::iterator here=instList.begin();
178   here=++front->getInstList().insert(here, rVar);
179   here=++front->getInstList().insert(here,countVar);
180   
181   //Initialize Count[...] with 0
182   for(int i=0;i<k; i++){
183     Instruction *stInstrC=new 
184       StoreInst(ConstantInt::get(Type::IntTy, 0), 
185                 countVar, std::vector<Value *>
186                 (1,ConstantUInt::get(Type::UIntTy, i))); 
187     here=++front->getInstList().insert(here,stInstrC);
188   }
189   
190   here=++front->getInstList().insert(here,stInstr);
191 }
192
193
194 //insert a basic block with appropriate code
195 //along a given edge
196 void insertBB(Edge ed,
197               getEdgeCode *edgeCode, 
198               Instruction *rInst, 
199               Instruction *countInst){
200
201   BasicBlock* BB1=ed.getFirst()->getElement();
202   BasicBlock* BB2=ed.getSecond()->getElement();
203   
204   DEBUG(cerr << "Edges with codes ######################\n";
205         cerr << BB1->getName() << "->" << BB2->getName() << "\n";
206         cerr << "########################\n");
207
208   //We need to insert a BB between BB1 and BB2 
209   TerminatorInst *TI=BB1->getTerminator();
210   BasicBlock *newBB=new BasicBlock("counter", BB1->getParent());
211
212   //get code for the new BB
213   edgeCode->getCode(rInst, countInst, BB1->getParent(), newBB);
214  
215   //Is terminator a branch instruction?
216   //then we need to change branch destinations to include new BB
217
218   BranchInst *BI=cast<BranchInst>(TI);
219  
220   if(BI->isUnconditional()){
221     BI->setUnconditionalDest(newBB);
222     Instruction *newBI2=new BranchInst(BB2);
223     newBB->getInstList().push_back(newBI2);
224   }
225   else{
226     Value *cond=BI->getCondition();
227     BasicBlock *fB, *tB;
228    
229     if (BI->getSuccessor(0) == BB2){
230       tB=newBB;
231       fB=BI->getSuccessor(1);
232     } else {
233       fB=newBB;
234       tB=BI->getSuccessor(0);
235     }
236    
237     BB1->getInstList().pop_back();
238     BB1->getInstList().push_back(new BranchInst(tB,fB,cond));
239     newBB->getInstList().push_back(new BranchInst(BB2));
240   }
241   
242   //now iterate over BB2, and set its Phi nodes right
243   for(BasicBlock::iterator BB2Inst = BB2->begin(), BBend = BB2->end(); 
244       BB2Inst != BBend; ++BB2Inst){
245    
246     if(PHINode *phiInst=dyn_cast<PHINode>(&*BB2Inst)){
247       DEBUG(cerr<<"YYYYYYYYYYYYYYYYY\n");
248
249       int bbIndex=phiInst->getBasicBlockIndex(BB1);
250       if(bbIndex>=0)
251         phiInst->setIncomingBlock(bbIndex, newBB);
252     }
253   }
254 }