Home | History | Annotate | Download | only in Analysis
      1 //===- ProfileInfoLoaderPass.cpp - LLVM Pass to load profile info ---------===//
      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 implements a concrete implementation of profiling information that
     11 // loads the information from a profile dump file.
     12 //
     13 //===----------------------------------------------------------------------===//
     14 #define DEBUG_TYPE "profile-loader"
     15 #include "llvm/BasicBlock.h"
     16 #include "llvm/InstrTypes.h"
     17 #include "llvm/Module.h"
     18 #include "llvm/Pass.h"
     19 #include "llvm/Analysis/Passes.h"
     20 #include "llvm/Analysis/ProfileInfo.h"
     21 #include "llvm/Analysis/ProfileInfoLoader.h"
     22 #include "llvm/Support/CommandLine.h"
     23 #include "llvm/Support/CFG.h"
     24 #include "llvm/Support/Debug.h"
     25 #include "llvm/Support/raw_ostream.h"
     26 #include "llvm/Support/Format.h"
     27 #include "llvm/ADT/Statistic.h"
     28 #include "llvm/ADT/SmallSet.h"
     29 #include <set>
     30 using namespace llvm;
     31 
     32 STATISTIC(NumEdgesRead, "The # of edges read.");
     33 
     34 static cl::opt<std::string>
     35 ProfileInfoFilename("profile-info-file", cl::init("llvmprof.out"),
     36                     cl::value_desc("filename"),
     37                     cl::desc("Profile file loaded by -profile-loader"));
     38 
     39 namespace {
     40   class LoaderPass : public ModulePass, public ProfileInfo {
     41     std::string Filename;
     42     std::set<Edge> SpanningTree;
     43     std::set<const BasicBlock*> BBisUnvisited;
     44     unsigned ReadCount;
     45   public:
     46     static char ID; // Class identification, replacement for typeinfo
     47     explicit LoaderPass(const std::string &filename = "")
     48       : ModulePass(ID), Filename(filename) {
     49       initializeLoaderPassPass(*PassRegistry::getPassRegistry());
     50       if (filename.empty()) Filename = ProfileInfoFilename;
     51     }
     52 
     53     virtual void getAnalysisUsage(AnalysisUsage &AU) const {
     54       AU.setPreservesAll();
     55     }
     56 
     57     virtual const char *getPassName() const {
     58       return "Profiling information loader";
     59     }
     60 
     61     // recurseBasicBlock() - Calculates the edge weights for as much basic
     62     // blocks as possbile.
     63     virtual void recurseBasicBlock(const BasicBlock *BB);
     64     virtual void readEdgeOrRemember(Edge, Edge&, unsigned &, double &);
     65     virtual void readEdge(ProfileInfo::Edge, std::vector<unsigned>&);
     66 
     67     /// getAdjustedAnalysisPointer - This method is used when a pass implements
     68     /// an analysis interface through multiple inheritance.  If needed, it
     69     /// should override this to adjust the this pointer as needed for the
     70     /// specified pass info.
     71     virtual void *getAdjustedAnalysisPointer(AnalysisID PI) {
     72       if (PI == &ProfileInfo::ID)
     73         return (ProfileInfo*)this;
     74       return this;
     75     }
     76 
     77     /// run - Load the profile information from the specified file.
     78     virtual bool runOnModule(Module &M);
     79   };
     80 }  // End of anonymous namespace
     81 
     82 char LoaderPass::ID = 0;
     83 INITIALIZE_AG_PASS(LoaderPass, ProfileInfo, "profile-loader",
     84               "Load profile information from llvmprof.out", false, true, false)
     85 
     86 char &llvm::ProfileLoaderPassID = LoaderPass::ID;
     87 
     88 ModulePass *llvm::createProfileLoaderPass() { return new LoaderPass(); }
     89 
     90 /// createProfileLoaderPass - This function returns a Pass that loads the
     91 /// profiling information for the module from the specified filename, making it
     92 /// available to the optimizers.
     93 Pass *llvm::createProfileLoaderPass(const std::string &Filename) {
     94   return new LoaderPass(Filename);
     95 }
     96 
     97 void LoaderPass::readEdgeOrRemember(Edge edge, Edge &tocalc,
     98                                     unsigned &uncalc, double &count) {
     99   double w;
    100   if ((w = getEdgeWeight(edge)) == MissingValue) {
    101     tocalc = edge;
    102     uncalc++;
    103   } else {
    104     count+=w;
    105   }
    106 }
    107 
    108 // recurseBasicBlock - Visits all neighbours of a block and then tries to
    109 // calculate the missing edge values.
    110 void LoaderPass::recurseBasicBlock(const BasicBlock *BB) {
    111 
    112   // break recursion if already visited
    113   if (BBisUnvisited.find(BB) == BBisUnvisited.end()) return;
    114   BBisUnvisited.erase(BB);
    115   if (!BB) return;
    116 
    117   for (succ_const_iterator bbi = succ_begin(BB), bbe = succ_end(BB);
    118        bbi != bbe; ++bbi) {
    119     recurseBasicBlock(*bbi);
    120   }
    121   for (const_pred_iterator bbi = pred_begin(BB), bbe = pred_end(BB);
    122        bbi != bbe; ++bbi) {
    123     recurseBasicBlock(*bbi);
    124   }
    125 
    126   Edge tocalc;
    127   if (CalculateMissingEdge(BB, tocalc)) {
    128     SpanningTree.erase(tocalc);
    129   }
    130 }
    131 
    132 void LoaderPass::readEdge(ProfileInfo::Edge e,
    133                           std::vector<unsigned> &ECs) {
    134   if (ReadCount < ECs.size()) {
    135     double weight = ECs[ReadCount++];
    136     if (weight != ProfileInfoLoader::Uncounted) {
    137       // Here the data realm changes from the unsigned of the file to the
    138       // double of the ProfileInfo. This conversion is save because we know
    139       // that everything thats representable in unsinged is also representable
    140       // in double.
    141       EdgeInformation[getFunction(e)][e] += (double)weight;
    142 
    143       DEBUG(dbgs() << "--Read Edge Counter for " << e
    144                    << " (# "<< (ReadCount-1) << "): "
    145                    << (unsigned)getEdgeWeight(e) << "\n");
    146     } else {
    147       // This happens only if reading optimal profiling information, not when
    148       // reading regular profiling information.
    149       SpanningTree.insert(e);
    150     }
    151   }
    152 }
    153 
    154 bool LoaderPass::runOnModule(Module &M) {
    155   ProfileInfoLoader PIL("profile-loader", Filename, M);
    156 
    157   EdgeInformation.clear();
    158   std::vector<unsigned> Counters = PIL.getRawEdgeCounts();
    159   if (Counters.size() > 0) {
    160     ReadCount = 0;
    161     for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) {
    162       if (F->isDeclaration()) continue;
    163       DEBUG(dbgs()<<"Working on "<<F->getNameStr()<<"\n");
    164       readEdge(getEdge(0,&F->getEntryBlock()), Counters);
    165       for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) {
    166         TerminatorInst *TI = BB->getTerminator();
    167         for (unsigned s = 0, e = TI->getNumSuccessors(); s != e; ++s) {
    168           readEdge(getEdge(BB,TI->getSuccessor(s)), Counters);
    169         }
    170       }
    171     }
    172     if (ReadCount != Counters.size()) {
    173       errs() << "WARNING: profile information is inconsistent with "
    174              << "the current program!\n";
    175     }
    176     NumEdgesRead = ReadCount;
    177   }
    178 
    179   Counters = PIL.getRawOptimalEdgeCounts();
    180   if (Counters.size() > 0) {
    181     ReadCount = 0;
    182     for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) {
    183       if (F->isDeclaration()) continue;
    184       DEBUG(dbgs()<<"Working on "<<F->getNameStr()<<"\n");
    185       readEdge(getEdge(0,&F->getEntryBlock()), Counters);
    186       for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) {
    187         TerminatorInst *TI = BB->getTerminator();
    188         if (TI->getNumSuccessors() == 0) {
    189           readEdge(getEdge(BB,0), Counters);
    190         }
    191         for (unsigned s = 0, e = TI->getNumSuccessors(); s != e; ++s) {
    192           readEdge(getEdge(BB,TI->getSuccessor(s)), Counters);
    193         }
    194       }
    195       while (SpanningTree.size() > 0) {
    196 
    197         unsigned size = SpanningTree.size();
    198 
    199         BBisUnvisited.clear();
    200         for (std::set<Edge>::iterator ei = SpanningTree.begin(),
    201              ee = SpanningTree.end(); ei != ee; ++ei) {
    202           BBisUnvisited.insert(ei->first);
    203           BBisUnvisited.insert(ei->second);
    204         }
    205         while (BBisUnvisited.size() > 0) {
    206           recurseBasicBlock(*BBisUnvisited.begin());
    207         }
    208 
    209         if (SpanningTree.size() == size) {
    210           DEBUG(dbgs()<<"{");
    211           for (std::set<Edge>::iterator ei = SpanningTree.begin(),
    212                ee = SpanningTree.end(); ei != ee; ++ei) {
    213             DEBUG(dbgs()<< *ei <<",");
    214           }
    215           assert(0 && "No edge calculated!");
    216         }
    217 
    218       }
    219     }
    220     if (ReadCount != Counters.size()) {
    221       errs() << "WARNING: profile information is inconsistent with "
    222              << "the current program!\n";
    223     }
    224     NumEdgesRead = ReadCount;
    225   }
    226 
    227   BlockInformation.clear();
    228   Counters = PIL.getRawBlockCounts();
    229   if (Counters.size() > 0) {
    230     ReadCount = 0;
    231     for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) {
    232       if (F->isDeclaration()) continue;
    233       for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB)
    234         if (ReadCount < Counters.size())
    235           // Here the data realm changes from the unsigned of the file to the
    236           // double of the ProfileInfo. This conversion is save because we know
    237           // that everything thats representable in unsinged is also
    238           // representable in double.
    239           BlockInformation[F][BB] = (double)Counters[ReadCount++];
    240     }
    241     if (ReadCount != Counters.size()) {
    242       errs() << "WARNING: profile information is inconsistent with "
    243              << "the current program!\n";
    244     }
    245   }
    246 
    247   FunctionInformation.clear();
    248   Counters = PIL.getRawFunctionCounts();
    249   if (Counters.size() > 0) {
    250     ReadCount = 0;
    251     for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) {
    252       if (F->isDeclaration()) continue;
    253       if (ReadCount < Counters.size())
    254         // Here the data realm changes from the unsigned of the file to the
    255         // double of the ProfileInfo. This conversion is save because we know
    256         // that everything thats representable in unsinged is also
    257         // representable in double.
    258         FunctionInformation[F] = (double)Counters[ReadCount++];
    259     }
    260     if (ReadCount != Counters.size()) {
    261       errs() << "WARNING: profile information is inconsistent with "
    262              << "the current program!\n";
    263     }
    264   }
    265 
    266   return false;
    267 }
    268