We won't use automake
[oota-llvm.git] / lib / Transforms / Instrumentation / ProfilePaths / ProfilePaths.cpp
1 //===-- ProfilePaths.cpp - interface to insert instrumentation --*- C++ -*-===//
2 // 
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file was developed by the LLVM research group and is distributed under
6 // the University of Illinois Open Source License. See LICENSE.TXT for details.
7 // 
8 //===----------------------------------------------------------------------===//
9 //
10 // This inserts instrumentation for counting execution of paths though a given
11 // function Its implemented as a "Function" Pass, and called using opt
12 //
13 // This pass is implemented by using algorithms similar to 
14 // 1."Efficient Path Profiling": Ball, T. and Larus, J. R., 
15 //    Proceedings of Micro-29, Dec 1996, Paris, France.
16 // 2."Efficiently Counting Program events with support for on-line
17 //   "queries": Ball T., ACM Transactions on Programming Languages
18 //    and systems, Sep 1994.
19 //
20 // The algorithms work on a Graph constructed over the nodes made from Basic
21 // Blocks: The transformations then take place on the constructed graph
22 // (implementation in Graph.cpp and GraphAuxiliary.cpp) and finally, appropriate
23 // instrumentation is placed over suitable edges.  (code inserted through
24 // EdgeCode.cpp).
25 // 
26 // The algorithm inserts code such that every acyclic path in the CFG of a
27 // function is identified through a unique number. the code insertion is optimal
28 // in the sense that its inserted over a minimal set of edges. Also, the
29 // algorithm makes sure than initialization, path increment and counter update
30 // can be collapsed into minimum number of edges.
31 //
32 //===----------------------------------------------------------------------===//
33
34 #include "llvm/Transforms/Utils/UnifyFunctionExitNodes.h"
35 #include "llvm/Support/CFG.h"
36 #include "llvm/Constants.h"
37 #include "llvm/DerivedTypes.h"
38 #include "llvm/Instructions.h"
39 #include "llvm/Module.h"
40 #include "Graph.h"
41 #include <fstream>
42 #include <cstdio>
43
44 namespace llvm {
45
46 struct ProfilePaths : public FunctionPass {
47   bool runOnFunction(Function &F);
48
49   // Before this pass, make sure that there is only one 
50   // entry and only one exit node for the function in the CFG of the function
51   //
52   void ProfilePaths::getAnalysisUsage(AnalysisUsage &AU) const {
53     AU.addRequired<UnifyFunctionExitNodes>();
54   }
55 };
56
57 static RegisterOpt<ProfilePaths> X("paths", "Profile Paths");
58
59 static Node *findBB(std::vector<Node *> &st, BasicBlock *BB){
60   for(std::vector<Node *>::iterator si=st.begin(); si!=st.end(); ++si){
61     if(((*si)->getElement())==BB){
62       return *si;
63     }
64   }
65   return NULL;
66 }
67
68 //Per function pass for inserting counters and trigger code
69 bool ProfilePaths::runOnFunction(Function &F){
70
71   static int mn = -1;
72   static int CountCounter = 1;
73   if(F.isExternal()) {
74     return false;
75   }
76  
77   //increment counter for instrumented functions. mn is now function#
78   mn++;
79   
80   // Transform the cfg s.t. we have just one exit node
81   BasicBlock *ExitNode = 
82     getAnalysis<UnifyFunctionExitNodes>().getReturnBlock();  
83
84   //iterating over BBs and making graph
85   std::vector<Node *> nodes;
86   std::vector<Edge> edges;
87
88   Node *tmp;
89   Node *exitNode = 0, *startNode = 0;
90
91   // The nodes must be uniquely identified:
92   // That is, no two nodes must hav same BB*
93   
94   for (Function::iterator BB = F.begin(), BE = F.end(); BB != BE; ++BB) {
95     Node *nd=new Node(BB);
96     nodes.push_back(nd); 
97     if(&*BB == ExitNode)
98       exitNode=nd;
99     if(BB==F.begin())
100       startNode=nd;
101   }
102
103   // now do it again to insert edges
104   for (Function::iterator BB = F.begin(), BE = F.end(); BB != BE; ++BB){
105     Node *nd=findBB(nodes, BB);
106     assert(nd && "No node for this edge!");
107
108     for(succ_iterator s=succ_begin(BB), se=succ_end(BB); s!=se; ++s){
109       Node *nd2=findBB(nodes,*s);
110       assert(nd2 && "No node for this edge!");
111       Edge ed(nd,nd2,0);
112       edges.push_back(ed);
113     }
114   }
115   
116   Graph g(nodes,edges, startNode, exitNode);
117
118 #ifdef DEBUG_PATH_PROFILES  
119   std::cerr<<"Original graph\n";
120   printGraph(g);
121 #endif
122
123   BasicBlock *fr = &F.front();
124   
125   // The graph is made acyclic: this is done
126   // by removing back edges for now, and adding them later on
127   std::vector<Edge> be;
128   std::map<Node *, int> nodePriority; //it ranks nodes in depth first order traversal
129   g.getBackEdges(be, nodePriority);
130   
131 #ifdef DEBUG_PATH_PROFILES
132   std::cerr<<"BackEdges-------------\n";
133   for (std::vector<Edge>::iterator VI=be.begin(); VI!=be.end(); ++VI){
134     printEdge(*VI);
135     cerr<<"\n";
136   }
137   std::cerr<<"------\n";
138 #endif
139
140 #ifdef DEBUG_PATH_PROFILES
141   cerr<<"Backedges:"<<be.size()<<endl;
142 #endif
143   //Now we need to reflect the effect of back edges
144   //This is done by adding dummy edges
145   //If a->b is a back edge
146   //Then we add 2 back edges for it:
147   //1. from root->b (in vector stDummy)
148   //and 2. from a->exit (in vector exDummy)
149   std::vector<Edge> stDummy;
150   std::vector<Edge> exDummy;
151   addDummyEdges(stDummy, exDummy, g, be);
152
153 #ifdef DEBUG_PATH_PROFILES
154   std::cerr<<"After adding dummy edges\n";
155   printGraph(g);
156 #endif
157
158   // Now, every edge in the graph is assigned a weight
159   // This weight later adds on to assign path
160   // numbers to different paths in the graph
161   //  All paths for now are acyclic,
162   // since no back edges in the graph now
163   // numPaths is the number of acyclic paths in the graph
164   int numPaths=valueAssignmentToEdges(g, nodePriority, be);
165
166   //if(numPaths<=1) return false;
167
168   static GlobalVariable *threshold = NULL;
169   static bool insertedThreshold = false;
170
171   if(!insertedThreshold){
172     threshold = new GlobalVariable(Type::IntTy, false,
173                                    GlobalValue::ExternalLinkage, 0,
174                                    "reopt_threshold");
175
176     F.getParent()->getGlobalList().push_back(threshold);
177     insertedThreshold = true;
178   }
179
180   assert(threshold && "GlobalVariable threshold not defined!");
181
182
183   if(fr->getParent()->getName() == "main"){
184     //initialize threshold
185
186     // FIXME: THIS IS HORRIBLY BROKEN.  FUNCTION PASSES CANNOT DO THIS, EXCEPT
187     // IN THEIR INITIALIZE METHOD!!
188     Function *initialize =
189       F.getParent()->getOrInsertFunction("reoptimizerInitialize", Type::VoidTy,
190                                          PointerType::get(Type::IntTy), 0);
191     
192     std::vector<Value *> trargs;
193     trargs.push_back(threshold);
194     new CallInst(initialize, trargs, "", fr->begin());
195   }
196
197
198   if(numPaths<=1 || numPaths >5000) return false;
199   
200 #ifdef DEBUG_PATH_PROFILES  
201   printGraph(g);
202 #endif
203
204   //create instruction allocation r and count
205   //r is the variable that'll act like an accumulator
206   //all along the path, we just add edge values to r
207   //and at the end, r reflects the path number
208   //count is an array: count[x] would store
209   //the number of executions of path numbered x
210
211   Instruction *rVar=new 
212     AllocaInst(Type::IntTy, 
213                ConstantUInt::get(Type::UIntTy,1),"R");
214
215   //Instruction *countVar=new 
216   //AllocaInst(Type::IntTy, 
217   //           ConstantUInt::get(Type::UIntTy, numPaths), "Count");
218
219   //initialize counter array!
220   std::vector<Constant*> arrayInitialize;
221   for(int xi=0; xi<numPaths; xi++)
222     arrayInitialize.push_back(ConstantSInt::get(Type::IntTy, 0));
223
224   const ArrayType *ATy = ArrayType::get(Type::IntTy, numPaths);
225   Constant *initializer =  ConstantArray::get(ATy, arrayInitialize);
226   char tempChar[20];
227   sprintf(tempChar, "Count%d", CountCounter);
228   CountCounter++;
229   std::string countStr = tempChar;
230   GlobalVariable *countVar = new GlobalVariable(ATy, false,
231                                                 GlobalValue::InternalLinkage, 
232                                                 initializer, countStr,
233                                                 F.getParent());
234   
235   // insert initialization code in first (entry) BB
236   // this includes initializing r and count
237   insertInTopBB(&F.getEntryBlock(), numPaths, rVar, threshold);
238     
239   //now process the graph: get path numbers,
240   //get increments along different paths,
241   //and assign "increments" and "updates" (to r and count)
242   //"optimally". Finally, insert llvm code along various edges
243   processGraph(g, rVar, countVar, be, stDummy, exDummy, numPaths, mn, 
244                threshold);    
245    
246   return true;  // Always modifies function
247 }
248
249 } // End llvm namespace