LLVM API Documentation

ProfileInfoLoader.cpp

Go to the documentation of this file.
00001 //===- ProfileInfoLoad.cpp - Load profile information from disk -----------===//
00002 //
00003 //                      The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // The ProfileInfoLoader class is used to load and represent profiling
00011 // information read in from the dump file.
00012 //
00013 //===----------------------------------------------------------------------===//
00014 
00015 #include "llvm/Analysis/ProfileInfoLoader.h"
00016 #include "llvm/Analysis/ProfileInfoTypes.h"
00017 #include "llvm/Module.h"
00018 #include "llvm/InstrTypes.h"
00019 #include "llvm/Support/Streams.h"
00020 #include <cstdio>
00021 #include <cstdlib>
00022 #include <map>
00023 using namespace llvm;
00024 
00025 // ByteSwap - Byteswap 'Var' if 'Really' is true.
00026 //
00027 static inline unsigned ByteSwap(unsigned Var, bool Really) {
00028   if (!Really) return Var;
00029   return ((Var & (255<< 0)) << 24) |
00030          ((Var & (255<< 8)) <<  8) |
00031          ((Var & (255<<16)) >>  8) |
00032          ((Var & (255<<24)) >> 24);
00033 }
00034 
00035 static void ReadProfilingBlock(const char *ToolName, FILE *F,
00036                                bool ShouldByteSwap,
00037                                std::vector<unsigned> &Data) {
00038   // Read the number of entries...
00039   unsigned NumEntries;
00040   if (fread(&NumEntries, sizeof(unsigned), 1, F) != 1) {
00041     cerr << ToolName << ": data packet truncated!\n";
00042     perror(0);
00043     exit(1);
00044   }
00045   NumEntries = ByteSwap(NumEntries, ShouldByteSwap);
00046 
00047   // Read the counts...
00048   std::vector<unsigned> TempSpace(NumEntries);
00049 
00050   // Read in the block of data...
00051   if (fread(&TempSpace[0], sizeof(unsigned)*NumEntries, 1, F) != 1) {
00052     cerr << ToolName << ": data packet truncated!\n";
00053     perror(0);
00054     exit(1);
00055   }
00056 
00057   // Make sure we have enough space...
00058   if (Data.size() < NumEntries)
00059     Data.resize(NumEntries);
00060 
00061   // Accumulate the data we just read into the data.
00062   if (!ShouldByteSwap) {
00063     for (unsigned i = 0; i != NumEntries; ++i)
00064       Data[i] += TempSpace[i];
00065   } else {
00066     for (unsigned i = 0; i != NumEntries; ++i)
00067       Data[i] += ByteSwap(TempSpace[i], true);
00068   }
00069 }
00070 
00071 // ProfileInfoLoader ctor - Read the specified profiling data file, exiting the
00072 // program if the file is invalid or broken.
00073 //
00074 ProfileInfoLoader::ProfileInfoLoader(const char *ToolName,
00075                                      const std::string &Filename,
00076                                      Module &TheModule) : M(TheModule) {
00077   FILE *F = fopen(Filename.c_str(), "r");
00078   if (F == 0) {
00079     cerr << ToolName << ": Error opening '" << Filename << "': ";
00080     perror(0);
00081     exit(1);
00082   }
00083 
00084   // Keep reading packets until we run out of them.
00085   unsigned PacketType;
00086   while (fread(&PacketType, sizeof(unsigned), 1, F) == 1) {
00087     // If the low eight bits of the packet are zero, we must be dealing with an
00088     // endianness mismatch.  Byteswap all words read from the profiling
00089     // information.
00090     bool ShouldByteSwap = (char)PacketType == 0;
00091     PacketType = ByteSwap(PacketType, ShouldByteSwap);
00092 
00093     switch (PacketType) {
00094     case ArgumentInfo: {
00095       unsigned ArgLength;
00096       if (fread(&ArgLength, sizeof(unsigned), 1, F) != 1) {
00097         cerr << ToolName << ": arguments packet truncated!\n";
00098         perror(0);
00099         exit(1);
00100       }
00101       ArgLength = ByteSwap(ArgLength, ShouldByteSwap);
00102 
00103       // Read in the arguments...
00104       std::vector<char> Chars(ArgLength+4);
00105 
00106       if (ArgLength)
00107         if (fread(&Chars[0], (ArgLength+3) & ~3, 1, F) != 1) {
00108           cerr << ToolName << ": arguments packet truncated!\n";
00109           perror(0);
00110           exit(1);
00111         }
00112       CommandLines.push_back(std::string(&Chars[0], &Chars[ArgLength]));
00113       break;
00114     }
00115 
00116     case FunctionInfo:
00117       ReadProfilingBlock(ToolName, F, ShouldByteSwap, FunctionCounts);
00118       break;
00119 
00120     case BlockInfo:
00121       ReadProfilingBlock(ToolName, F, ShouldByteSwap, BlockCounts);
00122       break;
00123 
00124     case EdgeInfo:
00125       ReadProfilingBlock(ToolName, F, ShouldByteSwap, EdgeCounts);
00126       break;
00127 
00128     case BBTraceInfo:
00129       ReadProfilingBlock(ToolName, F, ShouldByteSwap, BBTrace);
00130       break;
00131 
00132     default:
00133       cerr << ToolName << ": Unknown packet type #" << PacketType << "!\n";
00134       exit(1);
00135     }
00136   }
00137 
00138   fclose(F);
00139 }
00140 
00141 
00142 // getFunctionCounts - This method is used by consumers of function counting
00143 // information.  If we do not directly have function count information, we
00144 // compute it from other, more refined, types of profile information.
00145 //
00146 void ProfileInfoLoader::getFunctionCounts(std::vector<std::pair<Function*,
00147                                                       unsigned> > &Counts) {
00148   if (FunctionCounts.empty()) {
00149     if (hasAccurateBlockCounts()) {
00150       // Synthesize function frequency information from the number of times
00151       // their entry blocks were executed.
00152       std::vector<std::pair<BasicBlock*, unsigned> > BlockCounts;
00153       getBlockCounts(BlockCounts);
00154 
00155       for (unsigned i = 0, e = BlockCounts.size(); i != e; ++i)
00156         if (&BlockCounts[i].first->getParent()->getEntryBlock() ==
00157             BlockCounts[i].first)
00158           Counts.push_back(std::make_pair(BlockCounts[i].first->getParent(),
00159                                           BlockCounts[i].second));
00160     } else {
00161       cerr << "Function counts are not available!\n";
00162     }
00163     return;
00164   }
00165 
00166   unsigned Counter = 0;
00167   for (Module::iterator I = M.begin(), E = M.end();
00168        I != E && Counter != FunctionCounts.size(); ++I)
00169     if (!I->isDeclaration())
00170       Counts.push_back(std::make_pair(I, FunctionCounts[Counter++]));
00171 }
00172 
00173 // getBlockCounts - This method is used by consumers of block counting
00174 // information.  If we do not directly have block count information, we
00175 // compute it from other, more refined, types of profile information.
00176 //
00177 void ProfileInfoLoader::getBlockCounts(std::vector<std::pair<BasicBlock*,
00178                                                          unsigned> > &Counts) {
00179   if (BlockCounts.empty()) {
00180     if (hasAccurateEdgeCounts()) {
00181       // Synthesize block count information from edge frequency information.
00182       // The block execution frequency is equal to the sum of the execution
00183       // frequency of all outgoing edges from a block.
00184       //
00185       // If a block has no successors, this will not be correct, so we have to
00186       // special case it. :(
00187       std::vector<std::pair<Edge, unsigned> > EdgeCounts;
00188       getEdgeCounts(EdgeCounts);
00189 
00190       std::map<BasicBlock*, unsigned> InEdgeFreqs;
00191 
00192       BasicBlock *LastBlock = 0;
00193       TerminatorInst *TI = 0;
00194       for (unsigned i = 0, e = EdgeCounts.size(); i != e; ++i) {
00195         if (EdgeCounts[i].first.first != LastBlock) {
00196           LastBlock = EdgeCounts[i].first.first;
00197           TI = LastBlock->getTerminator();
00198           Counts.push_back(std::make_pair(LastBlock, 0));
00199         }
00200         Counts.back().second += EdgeCounts[i].second;
00201         unsigned SuccNum = EdgeCounts[i].first.second;
00202         if (SuccNum >= TI->getNumSuccessors()) {
00203           static bool Warned = false;
00204           if (!Warned) {
00205             cerr << "WARNING: profile info doesn't seem to match"
00206                  << " the program!\n";
00207             Warned = true;
00208           }
00209         } else {
00210           // If this successor has no successors of its own, we will never
00211           // compute an execution count for that block.  Remember the incoming
00212           // edge frequencies to add later.
00213           BasicBlock *Succ = TI->getSuccessor(SuccNum);
00214           if (Succ->getTerminator()->getNumSuccessors() == 0)
00215             InEdgeFreqs[Succ] += EdgeCounts[i].second;
00216         }
00217       }
00218 
00219       // Now we have to accumulate information for those blocks without
00220       // successors into our table.
00221       for (std::map<BasicBlock*, unsigned>::iterator I = InEdgeFreqs.begin(),
00222              E = InEdgeFreqs.end(); I != E; ++I) {
00223         unsigned i = 0;
00224         for (; i != Counts.size() && Counts[i].first != I->first; ++i)
00225           /*empty*/;
00226         if (i == Counts.size()) Counts.push_back(std::make_pair(I->first, 0));
00227         Counts[i].second += I->second;
00228       }
00229 
00230     } else {
00231       cerr << "Block counts are not available!\n";
00232     }
00233     return;
00234   }
00235 
00236   unsigned Counter = 0;
00237   for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F)
00238     for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) {
00239       Counts.push_back(std::make_pair(BB, BlockCounts[Counter++]));
00240       if (Counter == BlockCounts.size())
00241         return;
00242     }
00243 }
00244 
00245 // getEdgeCounts - This method is used by consumers of edge counting
00246 // information.  If we do not directly have edge count information, we compute
00247 // it from other, more refined, types of profile information.
00248 //
00249 void ProfileInfoLoader::getEdgeCounts(std::vector<std::pair<Edge,
00250                                                   unsigned> > &Counts) {
00251   if (EdgeCounts.empty()) {
00252     cerr << "Edge counts not available, and no synthesis "
00253          << "is implemented yet!\n";
00254     return;
00255   }
00256 
00257   unsigned Counter = 0;
00258   for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F)
00259     for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB)
00260       for (unsigned i = 0, e = BB->getTerminator()->getNumSuccessors();
00261            i != e; ++i) {
00262         Counts.push_back(std::make_pair(Edge(BB, i), EdgeCounts[Counter++]));
00263         if (Counter == EdgeCounts.size())
00264           return;
00265       }
00266 }
00267 
00268 // getBBTrace - This method is used by consumers of basic-block trace
00269 // information.
00270 //
00271 void ProfileInfoLoader::getBBTrace(std::vector<BasicBlock *> &Trace) {
00272   if (BBTrace.empty ()) {
00273     cerr << "Basic block trace is not available!\n";
00274     return;
00275   }
00276   cerr << "Basic block trace loading is not implemented yet!\n";
00277 }



This web site is hosted by the Computer Science Department at the University of Illinois at Urbana-Champaign.