1 //===- PathProfileInfo.cpp ------------------------------------*- C++ -*---===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file defines the interface used by optimizers to load path profiles, 11 // and provides a loader pass which reads a path profile file. 12 // 13 //===----------------------------------------------------------------------===// 14 #define DEBUG_TYPE "path-profile-info" 15 16 #include "llvm/Module.h" 17 #include "llvm/Pass.h" 18 #include "llvm/Analysis/Passes.h" 19 #include "llvm/Analysis/ProfileInfoTypes.h" 20 #include "llvm/Analysis/PathProfileInfo.h" 21 #include "llvm/Support/CommandLine.h" 22 #include "llvm/Support/Debug.h" 23 #include "llvm/Support/raw_ostream.h" 24 25 #include <cstdio> 26 27 using namespace llvm; 28 29 // command line option for loading path profiles 30 static cl::opt<std::string> 31 PathProfileInfoFilename("path-profile-loader-file", cl::init("llvmprof.out"), 32 cl::value_desc("filename"), 33 cl::desc("Path profile file loaded by -path-profile-loader"), cl::Hidden); 34 35 namespace { 36 class PathProfileLoaderPass : public ModulePass, public PathProfileInfo { 37 public: 38 PathProfileLoaderPass() : ModulePass(ID) { } 39 ~PathProfileLoaderPass(); 40 41 // this pass doesn't change anything (only loads information) 42 virtual void getAnalysisUsage(AnalysisUsage &AU) const { 43 AU.setPreservesAll(); 44 } 45 46 // the full name of the loader pass 47 virtual const char* getPassName() const { 48 return "Path Profiling Information Loader"; 49 } 50 51 // required since this pass implements multiple inheritance 52 virtual void *getAdjustedAnalysisPointer(AnalysisID PI) { 53 if (PI == &PathProfileInfo::ID) 54 return (PathProfileInfo*)this; 55 return this; 56 } 57 58 // entry point to run the pass 59 bool runOnModule(Module &M); 60 61 // pass identification 62 static char ID; 63 64 private: 65 // make a reference table to refer to function by number 66 void buildFunctionRefs(Module &M); 67 68 // process argument info of a program from the input file 69 void handleArgumentInfo(); 70 71 // process path number information from the input file 72 void handlePathInfo(); 73 74 // array of references to the functions in the module 75 std::vector<Function*> _functions; 76 77 // path profile file handle 78 FILE* _file; 79 80 // path profile file name 81 std::string _filename; 82 }; 83 } 84 85 // register PathLoader 86 char PathProfileLoaderPass::ID = 0; 87 88 INITIALIZE_ANALYSIS_GROUP(PathProfileInfo, "Path Profile Information", 89 NoPathProfileInfo) 90 INITIALIZE_AG_PASS(PathProfileLoaderPass, PathProfileInfo, 91 "path-profile-loader", 92 "Load path profile information from file", 93 false, true, false) 94 95 char &llvm::PathProfileLoaderPassID = PathProfileLoaderPass::ID; 96 97 // link PathLoader as a pass, and make it available as an optimisation 98 ModulePass *llvm::createPathProfileLoaderPass() { 99 return new PathProfileLoaderPass; 100 } 101 102 // ---------------------------------------------------------------------------- 103 // PathEdge implementation 104 // 105 ProfilePathEdge::ProfilePathEdge (BasicBlock* source, BasicBlock* target, 106 unsigned duplicateNumber) 107 : _source(source), _target(target), _duplicateNumber(duplicateNumber) {} 108 109 // ---------------------------------------------------------------------------- 110 // Path implementation 111 // 112 113 ProfilePath::ProfilePath (unsigned int number, unsigned int count, 114 double countStdDev, PathProfileInfo* ppi) 115 : _number(number) , _count(count), _countStdDev(countStdDev), _ppi(ppi) {} 116 117 double ProfilePath::getFrequency() const { 118 return 100 * double(_count) / 119 double(_ppi->_functionPathCounts[_ppi->_currentFunction]); 120 } 121 122 static BallLarusEdge* getNextEdge (BallLarusNode* node, 123 unsigned int pathNumber) { 124 BallLarusEdge* best = 0; 125 126 for( BLEdgeIterator next = node->succBegin(), 127 end = node->succEnd(); next != end; next++ ) { 128 if( (*next)->getType() != BallLarusEdge::BACKEDGE && // no backedges 129 (*next)->getType() != BallLarusEdge::SPLITEDGE && // no split edges 130 (*next)->getWeight() <= pathNumber && // weight must be <= pathNumber 131 (!best || (best->getWeight() < (*next)->getWeight())) ) // best one? 132 best = *next; 133 } 134 135 return best; 136 } 137 138 ProfilePathEdgeVector* ProfilePath::getPathEdges() const { 139 BallLarusNode* currentNode = _ppi->_currentDag->getRoot (); 140 unsigned int increment = _number; 141 ProfilePathEdgeVector* pev = new ProfilePathEdgeVector; 142 143 while (currentNode != _ppi->_currentDag->getExit()) { 144 BallLarusEdge* next = getNextEdge(currentNode, increment); 145 146 increment -= next->getWeight(); 147 148 if( next->getType() != BallLarusEdge::BACKEDGE_PHONY && 149 next->getType() != BallLarusEdge::SPLITEDGE_PHONY && 150 next->getTarget() != _ppi->_currentDag->getExit() ) 151 pev->push_back(ProfilePathEdge( 152 next->getSource()->getBlock(), 153 next->getTarget()->getBlock(), 154 next->getDuplicateNumber())); 155 156 if( next->getType() == BallLarusEdge::BACKEDGE_PHONY && 157 next->getTarget() == _ppi->_currentDag->getExit() ) 158 pev->push_back(ProfilePathEdge( 159 next->getRealEdge()->getSource()->getBlock(), 160 next->getRealEdge()->getTarget()->getBlock(), 161 next->getDuplicateNumber())); 162 163 if( next->getType() == BallLarusEdge::SPLITEDGE_PHONY && 164 next->getSource() == _ppi->_currentDag->getRoot() ) 165 pev->push_back(ProfilePathEdge( 166 next->getRealEdge()->getSource()->getBlock(), 167 next->getRealEdge()->getTarget()->getBlock(), 168 next->getDuplicateNumber())); 169 170 // set the new node 171 currentNode = next->getTarget(); 172 } 173 174 return pev; 175 } 176 177 ProfilePathBlockVector* ProfilePath::getPathBlocks() const { 178 BallLarusNode* currentNode = _ppi->_currentDag->getRoot (); 179 unsigned int increment = _number; 180 ProfilePathBlockVector* pbv = new ProfilePathBlockVector; 181 182 while (currentNode != _ppi->_currentDag->getExit()) { 183 BallLarusEdge* next = getNextEdge(currentNode, increment); 184 increment -= next->getWeight(); 185 186 // add block to the block list if it is a real edge 187 if( next->getType() == BallLarusEdge::NORMAL) 188 pbv->push_back (currentNode->getBlock()); 189 // make the back edge the last edge since we are at the end 190 else if( next->getTarget() == _ppi->_currentDag->getExit() ) { 191 pbv->push_back (currentNode->getBlock()); 192 pbv->push_back (next->getRealEdge()->getTarget()->getBlock()); 193 } 194 195 // set the new node 196 currentNode = next->getTarget(); 197 } 198 199 return pbv; 200 } 201 202 BasicBlock* ProfilePath::getFirstBlockInPath() const { 203 BallLarusNode* root = _ppi->_currentDag->getRoot(); 204 BallLarusEdge* edge = getNextEdge(root, _number); 205 206 if( edge && (edge->getType() == BallLarusEdge::BACKEDGE_PHONY || 207 edge->getType() == BallLarusEdge::SPLITEDGE_PHONY) ) 208 return edge->getTarget()->getBlock(); 209 210 return root->getBlock(); 211 } 212 213 // ---------------------------------------------------------------------------- 214 // PathProfileInfo implementation 215 // 216 217 // Pass identification 218 char llvm::PathProfileInfo::ID = 0; 219 220 PathProfileInfo::PathProfileInfo () : _currentDag(0) , _currentFunction(0) { 221 } 222 223 PathProfileInfo::~PathProfileInfo() { 224 if (_currentDag) 225 delete _currentDag; 226 } 227 228 // set the function for which paths are currently begin processed 229 void PathProfileInfo::setCurrentFunction(Function* F) { 230 // Make sure it exists 231 if (!F) return; 232 233 if (_currentDag) 234 delete _currentDag; 235 236 _currentFunction = F; 237 _currentDag = new BallLarusDag(*F); 238 _currentDag->init(); 239 _currentDag->calculatePathNumbers(); 240 } 241 242 // get the function for which paths are currently being processed 243 Function* PathProfileInfo::getCurrentFunction() const { 244 return _currentFunction; 245 } 246 247 // get the entry block of the function 248 BasicBlock* PathProfileInfo::getCurrentFunctionEntry() { 249 return _currentDag->getRoot()->getBlock(); 250 } 251 252 // return the path based on its number 253 ProfilePath* PathProfileInfo::getPath(unsigned int number) { 254 return _functionPaths[_currentFunction][number]; 255 } 256 257 // return the number of paths which a function may potentially execute 258 unsigned int PathProfileInfo::getPotentialPathCount() { 259 return _currentDag ? _currentDag->getNumberOfPaths() : 0; 260 } 261 262 // return an iterator for the beginning of a functions executed paths 263 ProfilePathIterator PathProfileInfo::pathBegin() { 264 return _functionPaths[_currentFunction].begin(); 265 } 266 267 // return an iterator for the end of a functions executed paths 268 ProfilePathIterator PathProfileInfo::pathEnd() { 269 return _functionPaths[_currentFunction].end(); 270 } 271 272 // returns the total number of paths run in the function 273 unsigned int PathProfileInfo::pathsRun() { 274 return _currentFunction ? _functionPaths[_currentFunction].size() : 0; 275 } 276 277 // ---------------------------------------------------------------------------- 278 // PathLoader implementation 279 // 280 281 // remove all generated paths 282 PathProfileLoaderPass::~PathProfileLoaderPass() { 283 for( FunctionPathIterator funcNext = _functionPaths.begin(), 284 funcEnd = _functionPaths.end(); funcNext != funcEnd; funcNext++) 285 for( ProfilePathIterator pathNext = funcNext->second.begin(), 286 pathEnd = funcNext->second.end(); pathNext != pathEnd; pathNext++) 287 delete pathNext->second; 288 } 289 290 // entry point of the pass; this loads and parses a file 291 bool PathProfileLoaderPass::runOnModule(Module &M) { 292 // get the filename and setup the module's function references 293 _filename = PathProfileInfoFilename; 294 buildFunctionRefs (M); 295 296 if (!(_file = fopen(_filename.c_str(), "rb"))) { 297 errs () << "error: input '" << _filename << "' file does not exist.\n"; 298 return false; 299 } 300 301 ProfilingType profType; 302 303 while( fread(&profType, sizeof(ProfilingType), 1, _file) ) { 304 switch (profType) { 305 case ArgumentInfo: 306 handleArgumentInfo (); 307 break; 308 case PathInfo: 309 handlePathInfo (); 310 break; 311 default: 312 errs () << "error: bad path profiling file syntax, " << profType << "\n"; 313 fclose (_file); 314 return false; 315 } 316 } 317 318 fclose (_file); 319 320 return true; 321 } 322 323 // create a reference table for functions defined in the path profile file 324 void PathProfileLoaderPass::buildFunctionRefs (Module &M) { 325 _functions.push_back(0); // make the 0 index a null pointer 326 327 for (Module::iterator F = M.begin(), E = M.end(); F != E; F++) { 328 if (F->isDeclaration()) 329 continue; 330 _functions.push_back(F); 331 } 332 } 333 334 // handle command like argument infor in the output file 335 void PathProfileLoaderPass::handleArgumentInfo() { 336 // get the argument list's length 337 unsigned savedArgsLength; 338 if( fread(&savedArgsLength, sizeof(unsigned), 1, _file) != 1 ) { 339 errs() << "warning: argument info header/data mismatch\n"; 340 return; 341 } 342 343 // allocate a buffer, and get the arguments 344 char* args = new char[savedArgsLength+1]; 345 if( fread(args, 1, savedArgsLength, _file) != savedArgsLength ) 346 errs() << "warning: argument info header/data mismatch\n"; 347 348 args[savedArgsLength] = '\0'; 349 argList = std::string(args); 350 delete [] args; // cleanup dynamic string 351 352 // byte alignment 353 if (savedArgsLength & 3) 354 fseek(_file, 4-(savedArgsLength&3), SEEK_CUR); 355 } 356 357 // Handle path profile information in the output file 358 void PathProfileLoaderPass::handlePathInfo () { 359 // get the number of functions in this profile 360 unsigned functionCount; 361 if( fread(&functionCount, sizeof(functionCount), 1, _file) != 1 ) { 362 errs() << "warning: path info header/data mismatch\n"; 363 return; 364 } 365 366 // gather path information for each function 367 for (unsigned i = 0; i < functionCount; i++) { 368 PathProfileHeader pathHeader; 369 if( fread(&pathHeader, sizeof(pathHeader), 1, _file) != 1 ) { 370 errs() << "warning: bad header for path function info\n"; 371 break; 372 } 373 374 Function* f = _functions[pathHeader.fnNumber]; 375 376 // dynamically allocate a table to store path numbers 377 PathProfileTableEntry* pathTable = 378 new PathProfileTableEntry[pathHeader.numEntries]; 379 380 if( fread(pathTable, sizeof(PathProfileTableEntry), 381 pathHeader.numEntries, _file) != pathHeader.numEntries) { 382 delete [] pathTable; 383 errs() << "warning: path function info header/data mismatch\n"; 384 return; 385 } 386 387 // Build a new path for the current function 388 unsigned int totalPaths = 0; 389 for (unsigned int j = 0; j < pathHeader.numEntries; j++) { 390 totalPaths += pathTable[j].pathCounter; 391 _functionPaths[f][pathTable[j].pathNumber] 392 = new ProfilePath(pathTable[j].pathNumber, pathTable[j].pathCounter, 393 0, this); 394 } 395 396 _functionPathCounts[f] = totalPaths; 397 398 delete [] pathTable; 399 } 400 } 401 402 //===----------------------------------------------------------------------===// 403 // NoProfile PathProfileInfo implementation 404 // 405 406 namespace { 407 struct NoPathProfileInfo : public ImmutablePass, public PathProfileInfo { 408 static char ID; // Class identification, replacement for typeinfo 409 NoPathProfileInfo() : ImmutablePass(ID) { 410 initializeNoPathProfileInfoPass(*PassRegistry::getPassRegistry()); 411 } 412 413 /// getAdjustedAnalysisPointer - This method is used when a pass implements 414 /// an analysis interface through multiple inheritance. If needed, it 415 /// should override this to adjust the this pointer as needed for the 416 /// specified pass info. 417 virtual void *getAdjustedAnalysisPointer(AnalysisID PI) { 418 if (PI == &PathProfileInfo::ID) 419 return (PathProfileInfo*)this; 420 return this; 421 } 422 423 virtual const char *getPassName() const { 424 return "NoPathProfileInfo"; 425 } 426 }; 427 } // End of anonymous namespace 428 429 char NoPathProfileInfo::ID = 0; 430 // Register this pass... 431 INITIALIZE_AG_PASS(NoPathProfileInfo, PathProfileInfo, "no-path-profile", 432 "No Path Profile Information", false, true, true) 433 434 ImmutablePass *llvm::createNoPathProfileInfoPass() { return new NoPathProfileInfo(); } 435