1 #ifndef _QPROF_COMMON_H
2 #define _QPROF_COMMON_H
3 
4 #include <cstdlib>
5 #include <common/util/stdlib.h>
6 
7 #define QPROF_SEP   ","
8 #define QPROF_SEP2  ":"
9 #define QPROF_SEP3  "|"
10 
11 #define QPROF_DECLARE_LL_SITESTACKS_OPT(P, VAR) \
12     static cl::opt<std::string> \
13     VAR(#P "-ll-sitestacks", \
14         cl::desc("Specify all the long-lived sitestacks on a per-task basis in qprof format"), \
15         cl::init(""), cl::NotHidden, cl::ValueRequired)
16 
17 #define QPROF_DECLARE_DEEPEST_LL_LOOPS_OPT(P, VAR) \
18     static cl::opt<std::string> \
19     VAR(#P "-deepest-ll-loops", \
20         cl::desc("Specify all the deepest long-lived loops on a per-task basis in qprof format"), \
21         cl::init(""), cl::NotHidden, cl::ValueRequired)
22 
23 #define QPROF_DECLARE_DEEPEST_LL_LIBS_OPT(P, VAR) \
24     static cl::opt<std::string> \
25     VAR(#P "-deepest-ll-libs", \
26         cl::desc("Specify all the deepest long-lived loop lib calls on a per-task basis in qprof format"), \
27         cl::init(""), cl::NotHidden, cl::ValueRequired)
28 
29 #define QPROF_DECLARE_TASK_CLASSES_OPT(P, VAR) \
30     static cl::opt<std::string> \
31     VAR(#P "-task-classes", \
32         cl::desc("Specify all the task classes in qprof format"), \
33         cl::init(""), cl::NotHidden, cl::ValueRequired)
34 
35 #define QPROF_DECLARE_ALL_OPTS(P, VAR1, VAR2, VAR3, VAR4) \
36     QPROF_DECLARE_LL_SITESTACKS_OPT(P, VAR1); \
37     QPROF_DECLARE_DEEPEST_LL_LOOPS_OPT(P, VAR2); \
38     QPROF_DECLARE_DEEPEST_LL_LIBS_OPT(P, VAR3); \
39     QPROF_DECLARE_TASK_CLASSES_OPT(P, VAR4) \
40 
41 using namespace llvm;
42 
43 namespace llvm {
44 
45 class QProfSite {
46   public:
47       static QProfSite* get(Module &M, int taskClassID, int taskSiteID, std::string moduleName, int lineNum, std::string functionName, std::string siteName, std::string siteFuncName, int siteDepth, int lib, unsigned long libFlags, bool refreshSite=true);
48       static QProfSite* getFromString(Module &M, int taskClassID, int taskSiteID, std::string &siteString, bool refreshSite=true);
49       static std::vector<QProfSite*> getFromSitesString(Module &M, std::string &sitesString, bool refreshSites=true);
50 
51       void refresh(Module &M);
52       std::string toString();
53       bool isLoop();
54       bool isFunction();
55       bool isCallsite();
56       bool isLibCallsite();
57       bool equals(QProfSite *other);
58 
59       int taskClassID;
60       int taskSiteID;
61       std::string moduleName;
62       int lineNum;
63       std::string functionName;
64       std::string siteName;
65       std::string siteFuncName;
66       unsigned long libFlags;
67       Function *function;
68       Function *siteFunction;
69       Instruction *siteInstruction;
70   private:
71       QProfSite() {}
72 
73       int siteDepth;
74       int lib;
75 };
76 
77 class QProfConf {
78   public:
79       static QProfConf* get(Module &M, std::string *llSitestacks, std::string *deepestLLLoops, std::string *deepestLLLibs, std::string *taskClasses, bool refreshSites=true);
80 
81       std::map<int, std::vector<QProfSite*> > getTaskClassLLSitestacks();
82       std::map<int, QProfSite*> getTaskClassDeepestLLLoops();
83       std::map<int, std::vector<QProfSite*> > getTaskClassDeepestLLLibs();
84       int getNumTaskClasses();
85       int getNumLLTaskClasses();
86       int getNumLLBlockExtTaskClasses();
87       int getNumLLBlockIntTaskClasses();
88       int getNumLLBlockExtLibs();
89       int getNumLLBlockIntLibs();
90 
91       std::vector<QProfSite*> getLLFunctions();
92       std::vector<QProfSite*> getDeepestLLLoops();
93       std::vector<QProfSite*> getDeepestLLLibs();
94       bool lookupTaskClassLibFlags(int taskClassID, int *libFlags);
95       void mergeTaskClassLLSitestacks(int taskClassID, int otherTaskClassID);
96       void mergeTaskClassDeepestLLLoops(int taskClassID, int otherTaskClassID);
97       void mergeTaskClassDeepestLLLibs(int taskClassID, int otherTaskClassID);
98       void mergeTaskClassPair(int taskClassID, int otherTaskClassID);
99       void mergeAllTaskClassesWithSameDeepestLLLoops();
100       void print(raw_ostream &O);
101       void printSiteList(raw_ostream &O, std::vector<QProfSite*> &list);
102 
103   private:
104       QProfConf() {}
105 
106       static std::map<int, std::vector<QProfSite*> > parseTaskClassSiteList(Module &M, std::string &str, bool refreshSites=true);
107       static std::map<int, QProfSite*> parseTaskClassSite(Module &M, std::string &str, bool refreshSites=true);
108       static std::vector<int> parseIntList(std::string &str);
109 
110       std::map<int, std::vector<QProfSite*> > taskClassLLSitestacks;
111       std::map<int, QProfSite*> taskClassDeepestLLLoops;
112       std::map<int, std::vector<QProfSite*> > taskClassDeepestLLLibs;
113       int numTaskClasses;
114       int numLLTaskClasses;
115       int numLLBlockExtTaskClasses;
116       int numLLBlockIntTaskClasses;
117       int numLLBlockExtLibs;
118       int numLLBlockIntLibs;
119 };
120 
121 static int stringRefToInt(StringRef &ref)
122 {
123     return atoi(ref.str().c_str());
124 }
125 
126 inline QProfSite* QProfSite::get(Module &M, int taskClassID, int taskSiteID,
127     std::string moduleName, int lineNum, std::string functionName,
128     std::string siteName, std::string siteFuncName, int siteDepth, int lib,
129     unsigned long libFlags, bool refreshSite)
130 {
131     QProfSite *site = new QProfSite();
132     site->taskClassID = taskClassID;
133     site->taskSiteID = taskSiteID;
134     site->moduleName = moduleName;
135     site->lineNum = lineNum;
136     site->functionName = functionName;
137     site->siteName = siteName;
138     site->siteFuncName = siteFuncName;
139     site->siteDepth = siteDepth;
140     site->lib = lib;
141     site->libFlags = libFlags;
142     site->function = NULL;
143     site->siteFunction = NULL;
144     site->siteInstruction = NULL;
145     if (refreshSite) {
146         site->refresh(M);
147     }
148 
149     return site;
150 }
151 
152 inline QProfSite* QProfSite::getFromString(Module &M, int taskClassID, int taskSiteID,
153     std::string &siteString, bool refreshSite)
154 {
155     StringRef ref(siteString);
156     SmallVector< StringRef, 3 > tokenVector;
157     if (!siteString.compare("")) {
158         return NULL;
159     }
160     ref.split(tokenVector, QPROF_SEP3);
161     assert(tokenVector.size() == 8);
162     return get(M, taskClassID, taskSiteID, tokenVector[0], stringRefToInt(tokenVector[1]),
163         tokenVector[2], tokenVector[3], tokenVector[4],
164         stringRefToInt(tokenVector[5]), stringRefToInt(tokenVector[6]),
165         stringRefToInt(tokenVector[7]), refreshSite);
166 }
167 
168 inline std::vector<QProfSite*> QProfSite::getFromSitesString(Module &M,
169     std::string &sitesString, bool refreshSites)
170 {
171     unsigned i;
172     int taskClassID;
173     std::vector<QProfSite*> sites;
174     StringRef ref(sitesString);
175     SmallVector< StringRef, 3 > tokenVector;
176     if (!sitesString.compare("")) {
177         return sites;
178     }
179     ref.split(tokenVector, QPROF_SEP2);
180     assert(tokenVector.size() > 1);
181     taskClassID = stringRefToInt(tokenVector[0]);
182     for (i=1;i<tokenVector.size();i++) {
183         std::string token = tokenVector[i].str();
184         QProfSite *site = QProfSite::getFromString(M, taskClassID, i, token,
185             refreshSites);
186         sites.push_back(site);
187     }
188     return sites;
189 }
190 
191 inline void QProfSite::refresh(Module &M)
192 {
193     BasicBlock *siteBB = NULL;
194     function = NULL;
195     siteFunction = NULL;
196     siteInstruction = NULL;
197     function = M.getFunction(functionName);
198     siteFunction = M.getFunction(siteFuncName);
199     if (!siteFunction) {
200         errs() << "Function " << siteFuncName << " not found. Invalid qprof profiling data?\n";
201     }
202     assert(siteFunction);
203     for (Function::iterator BB = siteFunction->begin(),
204         e = siteFunction->end(); BB != e; ++BB) {
205         if (!BB->getName().compare(siteName)) {
206             siteBB = BB;
207             break;
208         }
209     }
210     assert(siteBB);
211     if (isCallsite()) {
212         for (BasicBlock::iterator it = siteBB->begin(); it != siteBB->end(); ++it) {
213             CallSite CS(it);
214             if (CS.getInstruction() && CS.getCalledFunction() == function) {
215                 siteInstruction = it;
216                 break;
217             }
218         }
219         assert(siteInstruction && "Invalid qprof callsite?");
220     }
221     else {
222         siteInstruction = &siteBB->front();
223     }
224 }
225 
226 inline std::string QProfSite::toString()
227 {
228     std::string str;
229     raw_string_ostream ostream(str);
230     ostream << taskClassID << QPROF_SEP3 << taskSiteID << QPROF_SEP3 << moduleName << QPROF_SEP3 << lineNum << QPROF_SEP3 << functionName << QPROF_SEP3 << siteName << QPROF_SEP3 << siteFuncName << QPROF_SEP3 << siteDepth << QPROF_SEP3 << lib << QPROF_SEP3 << libFlags;
231     ostream.flush();
232     return str;
233 }
234 
235 inline bool QProfSite::isLoop()
236 {
237     return siteDepth > 0;
238 }
239 
240 inline bool QProfSite::isFunction()
241 {
242     return !isLoop() && !isCallsite();
243 }
244 
245 inline bool QProfSite::isCallsite()
246 {
247     return isLibCallsite();
248 }
249 
250 inline bool QProfSite::isLibCallsite()
251 {
252     return lib != 0;
253 }
254 
255 inline bool QProfSite::equals(QProfSite *other)
256 {
257      if (lineNum != other->lineNum) {
258          return false;
259      }
260      if (libFlags != other->libFlags) {
261          return false;
262      }
263      if (moduleName.compare(other->moduleName)) {
264          return false;
265      }
266      if (functionName.compare(other->functionName)) {
267          return false;
268      }
269      if (siteName.compare(other->siteName)) {
270          return false;
271      }
272      if (siteFuncName.compare(other->siteFuncName)) {
273          return false;
274      }
275      return true;
276 }
277 
278 inline QProfConf* QProfConf::get(Module &M, std::string *llSitestacks,
279     std::string *deepestLLLoops, std::string *deepestLLLibs,
280     std::string *taskClasses, bool refreshSites)
281 {
282     std::vector<int> intValues;
283     QProfConf *conf = new QProfConf();
284     if (llSitestacks) {
285         conf->taskClassLLSitestacks = parseTaskClassSiteList(M,
286             *llSitestacks, refreshSites);
287     }
288     if (deepestLLLoops) {
289         conf->taskClassDeepestLLLoops = parseTaskClassSite(M,
290             *deepestLLLoops, refreshSites);
291     }
292     if (deepestLLLibs) {
293         conf->taskClassDeepestLLLibs = parseTaskClassSiteList(M,
294             *deepestLLLibs, refreshSites);
295     }
296     if (taskClasses) {
297         intValues = parseIntList(*taskClasses);
298     }
299     if (intValues.size() > 0) {
300         assert(intValues.size() == 6);
301         conf->numTaskClasses = intValues[0];
302         conf->numLLTaskClasses = intValues[1];
303         conf->numLLBlockExtTaskClasses = intValues[2];
304         conf->numLLBlockIntTaskClasses = intValues[3];
305         conf->numLLBlockExtLibs = intValues[4];
306         conf->numLLBlockIntLibs = intValues[5];
307     }
308     else {
309         conf->numTaskClasses = 0;
310         conf->numLLTaskClasses = 0;
311         conf->numLLBlockExtTaskClasses = 0;
312         conf->numLLBlockIntTaskClasses = 0;
313         conf->numLLBlockExtLibs = 0;
314         conf->numLLBlockIntLibs = 0;
315     }
316 
317     return conf;
318 }
319 
320 inline std::map<int, std::vector<QProfSite*> > QProfConf::getTaskClassLLSitestacks()
321 {
322     return taskClassLLSitestacks;
323 }
324 
325 inline std::map<int, QProfSite*> QProfConf::getTaskClassDeepestLLLoops()
326 {
327     return taskClassDeepestLLLoops;
328 }
329 
330 inline std::map<int, std::vector<QProfSite*> > QProfConf::getTaskClassDeepestLLLibs()
331 {
332     return taskClassDeepestLLLibs;
333 }
334 
335 inline int QProfConf::getNumTaskClasses()
336 {
337     return numTaskClasses;
338 }
339 
340 inline int QProfConf::getNumLLTaskClasses()
341 {
342     return numLLTaskClasses;
343 }
344 
345 inline int QProfConf::getNumLLBlockExtTaskClasses()
346 {
347     return numLLBlockExtTaskClasses;
348 }
349 
350 inline int QProfConf::getNumLLBlockIntTaskClasses()
351 {
352     return numLLBlockIntTaskClasses;
353 }
354 
355 inline int QProfConf::getNumLLBlockExtLibs()
356 {
357     return numLLBlockExtLibs;
358 }
359 
360 inline int QProfConf::getNumLLBlockIntLibs()
361 {
362     return numLLBlockIntLibs;
363 }
364 
365 inline std::vector<QProfSite*> QProfConf::getLLFunctions()
366 {
367     std::vector<QProfSite*> sites;
368     std::map<int, std::vector<QProfSite*> >::iterator it;
369     it = taskClassLLSitestacks.begin();
370     for (; it != taskClassLLSitestacks.end(); it++) {
371         std::vector<QProfSite*> *siteVector = &it->second;
372         for (unsigned i=0;i<siteVector->size();i++) {
373             QProfSite* site = (*siteVector)[i];
374             if (site->isFunction()) {
375                 sites.push_back((*siteVector)[i]);
376             }
377         }
378     }
379     return sites;
380 }
381 
382 inline std::vector<QProfSite*> QProfConf::getDeepestLLLoops()
383 {
384     std::vector<QProfSite*> sites;
385     std::map<int, QProfSite*>::iterator it;
386     it = taskClassDeepestLLLoops.begin();
387     for (; it != taskClassDeepestLLLoops.end(); it++) {
388         sites.push_back(it->second);
389     }
390     return sites;
391 }
392 
393 inline std::vector<QProfSite*> QProfConf::getDeepestLLLibs()
394 {
395     std::vector<QProfSite*> sites;
396     std::map<int, std::vector<QProfSite*> >::iterator it;
397     it = taskClassDeepestLLLibs.begin();
398     for (; it != taskClassDeepestLLLibs.end(); it++) {
399         std::vector<QProfSite*> *siteVector = &it->second;
400         for (unsigned i=0;i<siteVector->size();i++) {
401             sites.push_back((*siteVector)[i]);
402         }
403     }
404     return sites;
405 }
406 
407 inline bool QProfConf::lookupTaskClassLibFlags(int taskClassID, int *libFlags)
408 {
409     bool found = false;
410     std::vector<QProfSite*> deepestLLLibs = getDeepestLLLibs();
411 
412     *libFlags = 0;
413     for (unsigned i=0;i<deepestLLLibs.size();i++) {
414         QProfSite *site = deepestLLLibs[i];
415         if (site->taskClassID == taskClassID) {
416             *libFlags |= site->libFlags;
417             found = true;
418         }
419     }
420     return found;
421 }
422 
423 inline void QProfConf::mergeTaskClassLLSitestacks(int taskClassID, int otherTaskClassID)
424 {
425     size_t erased = taskClassLLSitestacks.erase(otherTaskClassID);
426     assert(erased == 1);
427 }
428 
429 inline void QProfConf::mergeTaskClassDeepestLLLoops(int taskClassID, int otherTaskClassID)
430 {
431     size_t erased = taskClassDeepestLLLoops.erase(otherTaskClassID);
432     assert(erased == 1);
433 }
434 
435 inline void QProfConf::mergeTaskClassDeepestLLLibs(int taskClassID, int otherTaskClassID)
436 {
437     size_t erased = taskClassDeepestLLLibs.erase(otherTaskClassID);
438     assert(erased == 1);
439 }
440 
441 inline void QProfConf::mergeTaskClassPair(int taskClassID,
442     int otherTaskClassID)
443 {
444     int libFlags;
445     mergeTaskClassLLSitestacks(taskClassID, otherTaskClassID);
446     mergeTaskClassDeepestLLLoops(taskClassID, otherTaskClassID);
447     mergeTaskClassDeepestLLLibs(taskClassID, otherTaskClassID);
448 
449     numTaskClasses--;
450     if (lookupTaskClassLibFlags(taskClassID, &libFlags)) {
451         numLLTaskClasses--;
452         if (libFlags & _UTIL_STLIB_FLAG(STLIB_BLOCK_EXT)) {
453             numLLBlockExtTaskClasses--;
454         }
455         else {
456             numLLBlockIntTaskClasses--;
457         }
458     }
459 }
460 
461 inline void QProfConf::mergeAllTaskClassesWithSameDeepestLLLoops()
462 {
463     std::vector<QProfSite*> deepestLLLoops = getDeepestLLLoops();
464     std::vector<std::pair<QProfSite*, QProfSite*> > loopPairs;
465 
466     for (unsigned i=0;i<deepestLLLoops.size();i++) {
467         QProfSite *site = deepestLLLoops[i];
468         for (unsigned j=0;j<i;j++) {
469             if (site->equals(deepestLLLoops[j])) {
470                 loopPairs.push_back(std::pair<QProfSite*, QProfSite*>(site, deepestLLLoops[j]));
471             }
472         }
473     }
474     for (unsigned i=0;i<loopPairs.size();i++) {
475         int taskClassID = loopPairs[i].first->taskClassID;
476         int otherTaskClassID = loopPairs[i].second->taskClassID;
477         mergeTaskClassPair(taskClassID, otherTaskClassID);
478     }
479 }
480 
481 inline void QProfConf::print(raw_ostream &O)
482 {
483     std::vector<QProfSite*> list;
484     O << "*** QProfConf:\n";
485     O << " - numTaskClasses=" << getNumTaskClasses() << "\n";
486     O << " - numLLTaskClasses=" << getNumLLTaskClasses() << "\n";
487     O << " - numLLBlockExtTaskClasses=" << getNumLLBlockExtTaskClasses() << "\n";
488     O << " - numLLBlockIntTaskClasses=" << getNumLLBlockIntTaskClasses() << "\n";
489     O << " - numLLBlockExtLibs=" << getNumLLBlockExtLibs() << "\n";
490     O << " - numLLBlockIntLibs=" << getNumLLBlockIntLibs() << "\n";
491     list =  getLLFunctions();
492     O << " - LLFunctions="; printSiteList(O, list); O << "\n";
493     list = getDeepestLLLoops();
494     O << " - deepestLLLoops="; printSiteList(O, list); O << "\n";
495     list = getDeepestLLLibs();
496     O << " - deepestLLLibs="; printSiteList(O, list); O << "\n";
497 }
498 
499 inline void QProfConf::printSiteList(raw_ostream &O, std::vector<QProfSite*> &list)
500 {
501     for (std::vector<QProfSite*>::iterator it = list.begin(); it != list.end(); it++) {
502         QProfSite* site = *it;
503         if (it != list.begin()) {
504             O << ", ";
505         }
506         O << "{ ";
507         O << site->toString();
508         O << " }";
509     }
510 }
511 
512 inline std::map<int, std::vector<QProfSite*> > QProfConf::parseTaskClassSiteList(Module &M,
513     std::string &str, bool refreshSites)
514 {
515     std::map<int, std::vector<QProfSite*> > siteListMap;
516     StringRef ref(str);
517     SmallVector< StringRef, 3 > tokenVector;
518     if (!str.compare("")) {
519         return siteListMap;
520     }
521     ref.split(tokenVector, QPROF_SEP);
522     for (unsigned i=0;i<tokenVector.size();i++) {
523         std::string token = tokenVector[i].str();
524         std::vector<QProfSite*> sites = QProfSite::getFromSitesString(M,
525             token, refreshSites);
526         if (sites.size() > 0) {
527             int taskClassID = sites[0]->taskClassID;
528             siteListMap.insert(std::pair<int, std::vector<QProfSite*> >(taskClassID,
529                 sites));
530         }
531     }
532     return siteListMap;
533 }
534 
535 inline std::map<int, QProfSite*> QProfConf::parseTaskClassSite(Module &M,
536     std::string &str, bool refreshSites)
537 {
538     std::map<int, std::vector<QProfSite*> >::iterator it;
539     std::map<int, std::vector<QProfSite*> > siteListMap =
540         parseTaskClassSiteList(M, str, refreshSites);
541     std::map<int, QProfSite*> siteMap;
542     for (it=siteListMap.begin();it!=siteListMap.end();it++) {
543         std::vector<QProfSite*> list = it->second;
544         assert(list.size() == 1);
545         siteMap.insert(std::pair<int, QProfSite*>(it->first, list[0]));
546     }
547 
548     return siteMap;
549 }
550 
551 inline std::vector<int> QProfConf::parseIntList(std::string &str)
552 {
553     std::vector<int> intValues;
554     StringRef ref(str);
555     SmallVector< StringRef, 3 > tokenVector;
556     if (!str.compare("")) {
557         return intValues;
558     }
559     ref.split(tokenVector, QPROF_SEP);
560     for (unsigned i=0;i<tokenVector.size();i++) {
561         intValues.push_back(stringRefToInt(tokenVector[i]));
562     }
563 
564     return intValues;
565 }
566 
567 }
568 
569 #endif /* _QPROF_COMMON_H */
570