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