Fix bug I introduced
[oota-llvm.git] / lib / Transforms / Instrumentation / ProfilePaths / EdgeCode.cpp
1 //===-- EdgeCode.cpp - generate LLVM instrumentation code -----------------===//
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 "llvm/Transforms/Instrumentation/Graph.h"
11 #include "llvm/Constants.h"
12 #include "llvm/DerivedTypes.h"
13 #include "llvm/iMemory.h"
14 #include "llvm/iTerminators.h"
15 #include "llvm/iOther.h"
16 #include "llvm/iOperators.h"
17 #include "llvm/iPHINode.h"
18 #include "llvm/Module.h"
19 #include <string.h>
20 #include <stdio.h>
21
22 #define INSERT_LOAD_COUNT
23 #define INSERT_STORE
24
25 using std::vector;
26
27
28 static void getTriggerCode(Module *M, BasicBlock *BB, int MethNo, Value *pathNo,
29                            Value *cnt, Instruction *InsertPos){ 
30   static int i=-1;
31   i++;
32   char gstr[100];
33   sprintf(gstr,"globalVar%d",i);
34   std::string globalVarName=gstr;
35   vector<const Type*> args;
36   //args.push_back(PointerType::get(Type::SByteTy));
37   args.push_back(Type::IntTy);
38   args.push_back(Type::IntTy);
39   args.push_back(Type::IntTy);
40   const FunctionType *MTy = FunctionType::get(Type::VoidTy, args, false);
41
42   //  Function *triggerMeth = M->getOrInsertFunction("trigger", MTy);
43   Function *trigMeth = M->getOrInsertFunction("trigger", MTy);
44   assert(trigMeth && "trigger method could not be inserted!");
45   //if (Value *triggerMeth = ST->lookup(PointerType::get(MTy), "trigger")) {
46   //Function *trigMeth = cast<Function>(triggerMeth);
47   vector<Value *> trargs;
48
49   //pred_iterator piter=BB->pred_begin();
50   //std::string predName = "uu";//BB->getName();
51   //Constant *bbName=ConstantArray::get(predName);//BB->getName());
52   //GlobalVariable *gbl=new GlobalVariable(ArrayType::get(Type::SByteTy, 
53   //                                    predName.size()+1), 
54   //                             true, true, bbName, gstr);
55   
56   //M->getGlobalList().push_back(gbl);
57
58   //vector<Value *> elargs;
59   //elargs.push_back(ConstantSInt::get(Type::LongTy, 0));
60   //elargs.push_back(ConstantSInt::get(Type::LongTy, 0));
61
62   // commented out bb name frm which its called
63   //Instruction *getElmntInst=new GetElementPtrInst(gbl,elargs,"elmntInst");
64   
65   //trargs.push_back(ConstantArray::get(BB->getName()));
66   
67   //trargs.push_back(getElmntInst);
68   //trargs.push_back(bbName);
69
70   trargs.push_back(ConstantSInt::get(Type::IntTy,MethNo));
71     
72   //trargs.push_back(ConstantSInt::get(Type::IntTy,-1));//erase this
73   trargs.push_back(pathNo);
74   trargs.push_back(cnt);
75   Instruction *callInst=new CallInst(trigMeth, trargs, "", InsertPos);
76 }
77
78
79 //get the code to be inserted on the edge
80 //This is determined from cond (1-6)
81 void getEdgeCode::getCode(Instruction *rInst, 
82                           Instruction *countInst, 
83                           Function *M, 
84                           BasicBlock *BB, int numPaths, int MethNo){
85   
86   Instruction *InsertPos = BB->begin();
87   
88   //case: r=k code to be inserted
89   switch(cond){
90   case 1:{
91     Value *val=ConstantSInt::get(Type::IntTy,inc);
92 #ifdef INSERT_STORE
93     Instruction *stInst=new StoreInst(val, rInst, InsertPos);
94 #endif
95     break;
96     }
97
98   //case: r=0 to be inserted
99   case 2:
100 #ifdef INSERT_STORE
101     new StoreInst(ConstantSInt::getNullValue(Type::IntTy), rInst, InsertPos);
102 #endif
103     break;
104     
105   //r+=k
106   case 3:{
107     Instruction *ldInst = new LoadInst(rInst, "ti1", InsertPos);
108     Value *val = ConstantSInt::get(Type::IntTy,inc);
109     Value *addIn = BinaryOperator::create(Instruction::Add, ldInst, val,
110                                           "ti2", InsertPos);
111 #ifdef INSERT_STORE
112     new StoreInst(addIn, rInst, InsertPos);
113 #endif
114     break;
115   }
116
117   //count[inc]++
118   case 4:{
119     assert(inc>=0 && inc<=numPaths && "inc out of bound!");
120    
121     Instruction *Idx = new GetElementPtrInst(countInst, 
122                  vector<Value*>(1,ConstantSInt::get(Type::LongTy, inc)),
123                                              "", InsertPos);
124
125     Instruction *ldInst=new LoadInst(Idx, "ti1", InsertPos);
126  
127     Value *val = ConstantSInt::get(Type::IntTy, 1);
128     Instruction *addIn =
129       BinaryOperator::create(Instruction::Add, ldInst, val,"ti2", InsertPos);
130
131 #ifdef INSERT_STORE
132     Instruction *stInst=new StoreInst(addIn, Idx, InsertPos);
133 #endif
134
135     //insert trigger
136     getTriggerCode(M->getParent(), BB, MethNo, 
137                    ConstantSInt::get(Type::IntTy,inc), addIn, InsertPos);
138     //end trigger code
139
140     assert(inc>=0 && "IT MUST BE POSITIVE NOW");
141     break;
142   }
143
144   //case: count[r+inc]++
145   case 5:{
146    
147     //ti1=inc+r
148     Instruction *ldIndex=new LoadInst(rInst, "ti1", InsertPos);
149     Value *val=ConstantSInt::get(Type::IntTy,inc);
150     Instruction *addIndex=BinaryOperator::
151       create(Instruction::Add, ldIndex, val,"ti2", InsertPos);
152     //erase following 1 line
153     //Value *valtemp=ConstantSInt::get(Type::IntTy,999);
154     //now load count[addIndex]
155     
156     Instruction *castInst=new CastInst(addIndex, 
157                                        Type::LongTy,"ctin", InsertPos);
158     Instruction *Idx = new GetElementPtrInst(countInst, 
159                                              vector<Value*>(1,castInst), "",
160                                              InsertPos);
161
162     Instruction *ldInst=new LoadInst(Idx, "ti3", InsertPos);
163     Value *cons=ConstantSInt::get(Type::IntTy,1);
164     //count[addIndex]++
165     Value *addIn = BinaryOperator::create(Instruction::Add, ldInst, cons,
166                                           "ti4", InsertPos);
167     
168 #ifdef INSERT_STORE
169     ///*
170     new StoreInst(addIn, Idx, InsertPos);
171     //*/
172 #endif
173
174     //insert trigger
175     getTriggerCode(M->getParent(), BB, MethNo, addIndex, addIn, InsertPos);
176     //end trigger code
177
178     break;
179   }
180
181     //case: count[r]+
182   case 6:{
183     //ti1=inc+r
184     Instruction *ldIndex=new LoadInst(rInst, "ti1", InsertPos);
185     
186     //now load count[addIndex]
187     Instruction *castInst2=new CastInst(ldIndex, Type::LongTy,"ctin",InsertPos);
188     Instruction *Idx = new GetElementPtrInst(countInst, 
189                                              vector<Value*>(1,castInst2), "",
190                                              InsertPos);
191     
192     Instruction *ldInst=new LoadInst(Idx, "ti2", InsertPos);
193     Value *cons=ConstantSInt::get(Type::IntTy,1);
194
195     //count[addIndex]++
196     Instruction *addIn=BinaryOperator::create(Instruction::Add, ldInst,
197                                               cons,"ti3", InsertPos);
198
199 #ifdef INSERT_STORE
200     new StoreInst(addIn, Idx, InsertPos);
201 #endif
202     //insert trigger
203     getTriggerCode(M->getParent(), BB, MethNo, ldIndex, addIn, InsertPos);
204     //end trigger code
205     
206     break;
207   }
208     
209   }
210   //now check for cdIn and cdOut
211   //first put cdOut
212   if(cdIn!=NULL){
213     cdIn->getCode(rInst, countInst, M, BB, numPaths, MethNo);
214   }
215   if(cdOut!=NULL){
216     cdOut->getCode(rInst, countInst, M, BB, numPaths, MethNo);
217   }
218 }
219
220
221
222 //Insert the initialization code in the top BB
223 //this includes initializing r, and count
224 //r is like an accumulator, that 
225 //keeps on adding increments as we traverse along a path
226 //and at the end of the path, r contains the path
227 //number of that path
228 //Count is an array, where Count[k] represents
229 //the number of executions of path k
230 void insertInTopBB(BasicBlock *front, 
231                    int k, 
232                    Instruction *rVar, 
233                    Instruction *countVar){
234   //rVar is variable r, 
235   //countVar is array Count, and these are allocatted outside
236
237   Value *Int0 = ConstantInt::get(Type::IntTy, 0);
238   
239   //now push all instructions in front of the BB
240   BasicBlock::iterator here=front->begin();
241   front->getInstList().insert(here, rVar);
242   front->getInstList().insert(here,countVar);
243   
244   //Initialize Count[...] with 0
245
246   for (int i=0;i<k; i++){
247     Value *GEP2 = new GetElementPtrInst(countVar,
248                           vector<Value *>(1,ConstantSInt::get(Type::LongTy, i)),
249                                         "", here);
250     new StoreInst(Int0, GEP2, here);
251   }
252
253   //store uint 0, uint *%R
254   new StoreInst(Int0, rVar, here);
255 }
256
257
258 //insert a basic block with appropriate code
259 //along a given edge
260 void insertBB(Edge ed,
261               getEdgeCode *edgeCode, 
262               Instruction *rInst, 
263               Instruction *countInst, 
264               int numPaths, int Methno){
265   static int i=-1;
266   i++;
267   BasicBlock* BB1=ed.getFirst()->getElement();
268   BasicBlock* BB2=ed.getSecond()->getElement();
269   
270 #ifdef DEBUG_PATH_PROFILES
271   //debugging info
272   cerr<<"Edges with codes ######################\n";
273   cerr<<BB1->getName()<<"->"<<BB2->getName()<<"\n";
274   cerr<<"########################\n";
275 #endif
276   
277   char counterstr[100];
278   sprintf(counterstr,"counter%d",i);
279   std::string ctr=counterstr;
280
281   //We need to insert a BB between BB1 and BB2 
282   TerminatorInst *TI=BB1->getTerminator();
283   BasicBlock *newBB=new BasicBlock(ctr, BB1->getParent());
284
285   //Is terminator a branch instruction?
286   //then we need to change branch destinations to include new BB
287
288   //std::cerr<<"before cast!\n";
289   //std::cerr<<"Method no in Edgecode:"<<Methno<<"\n";
290   //std::cerr<<"Instruction\n";
291   //std::cerr<<*TI;
292   BranchInst *BI =  cast<BranchInst>(TI);
293
294   if(BI->isUnconditional()){
295     BI->setUnconditionalDest(newBB);
296     Instruction *newBI2=new BranchInst(BB2);
297     newBB->getInstList().push_back(newBI2);
298   }
299   else{
300       if(BI->getSuccessor(0)==BB2)
301       BI->setSuccessor(0, newBB);
302     
303     if(BI->getSuccessor(1)==BB2)
304       BI->setSuccessor(1, newBB);
305
306     Instruction *newBI2=new BranchInst(BB2);
307     newBB->getInstList().push_back(newBI2);
308   }
309
310   //get code for the new BB
311   edgeCode->getCode(rInst, countInst, BB1->getParent(), newBB, numPaths, Methno);
312
313   
314   //std::cerr<<"After casting\n";
315   //get code for the new BB
316    //now iterate over BB2, and set its Phi nodes right
317   for(BasicBlock::iterator BB2Inst = BB2->begin(), BBend = BB2->end(); 
318       BB2Inst != BBend; ++BB2Inst){
319    
320     if(PHINode *phiInst=dyn_cast<PHINode>(&*BB2Inst)){
321       int bbIndex=phiInst->getBasicBlockIndex(BB1);
322       assert(bbIndex>=0);
323       phiInst->setIncomingBlock(bbIndex, newBB);
324     }
325   }
326 }
327