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