PathProfileVerifier.cpp revision 221345
1218885Sdim//===- PathProfileVerifier.cpp --------------------------------*- C++ -*---===//
2218885Sdim//
3218885Sdim//                     The LLVM Compiler Infrastructure
4218885Sdim//
5218885Sdim// This file is distributed under the University of Illinois Open Source
6218885Sdim// License. See LICENSE.TXT for details.
7218885Sdim//
8218885Sdim//===----------------------------------------------------------------------===//
9218885Sdim//
10218885Sdim// This verifier derives an edge profile file from current path profile
11218885Sdim// information
12218885Sdim//
13218885Sdim//===----------------------------------------------------------------------===//
14218885Sdim#define DEBUG_TYPE "path-profile-verifier"
15218885Sdim
16218885Sdim#include "llvm/Module.h"
17218885Sdim#include "llvm/Pass.h"
18218885Sdim#include "llvm/Analysis/Passes.h"
19218885Sdim#include "llvm/Analysis/ProfileInfoTypes.h"
20218885Sdim#include "llvm/Analysis/PathProfileInfo.h"
21218885Sdim#include "llvm/Support/Debug.h"
22218885Sdim#include "llvm/Support/CommandLine.h"
23218885Sdim#include "llvm/Support/raw_ostream.h"
24218885Sdim
25218885Sdim#include <stdio.h>
26218885Sdim
27218885Sdimusing namespace llvm;
28218885Sdim
29218885Sdimnamespace {
30218885Sdim  class PathProfileVerifier : public ModulePass {
31218885Sdim  private:
32218885Sdim    bool runOnModule(Module &M);
33218885Sdim
34218885Sdim  public:
35218885Sdim    static char ID; // Pass identification, replacement for typeid
36218885Sdim    PathProfileVerifier() : ModulePass(ID) {
37218885Sdim      initializePathProfileVerifierPass(*PassRegistry::getPassRegistry());
38218885Sdim    }
39218885Sdim
40218885Sdim
41218885Sdim    virtual const char *getPassName() const {
42218885Sdim      return "Path Profiler Verifier";
43218885Sdim    }
44218885Sdim
45218885Sdim    // The verifier requires the path profile and edge profile.
46218885Sdim    virtual void getAnalysisUsage(AnalysisUsage& AU) const;
47218885Sdim  };
48218885Sdim}
49218885Sdim
50218885Sdimstatic cl::opt<std::string>
51218885SdimEdgeProfileFilename("path-profile-verifier-file",
52218885Sdim  cl::init("edgefrompath.llvmprof.out"),
53218885Sdim  cl::value_desc("filename"),
54218885Sdim  cl::desc("Edge profile file generated by -path-profile-verifier"),
55218885Sdim  cl::Hidden);
56218885Sdim
57218885Sdimchar PathProfileVerifier::ID = 0;
58218885SdimINITIALIZE_PASS(PathProfileVerifier, "path-profile-verifier",
59218885Sdim                "Compare the path profile derived edge profile against the "
60218885Sdim                "edge profile.", true, true)
61218885Sdim
62218885SdimModulePass *llvm::createPathProfileVerifierPass() {
63218885Sdim  return new PathProfileVerifier();
64218885Sdim}
65218885Sdim
66218885Sdim// The verifier requires the path profile and edge profile.
67218885Sdimvoid PathProfileVerifier::getAnalysisUsage(AnalysisUsage& AU) const {
68218885Sdim  AU.addRequired<PathProfileInfo>();
69218885Sdim  AU.addPreserved<PathProfileInfo>();
70218885Sdim}
71218885Sdim
72218885Sdimtypedef std::map<unsigned, unsigned> DuplicateToIndexMap;
73218885Sdimtypedef std::map<BasicBlock*,DuplicateToIndexMap> BlockToDuplicateMap;
74218885Sdimtypedef std::map<BasicBlock*,BlockToDuplicateMap> NestedBlockToIndexMap;
75218885Sdim
76218885Sdim// the verifier iterates through each path to gather the total
77218885Sdim// number of edge frequencies
78218885Sdimbool PathProfileVerifier::runOnModule (Module &M) {
79218885Sdim  PathProfileInfo& pathProfileInfo = getAnalysis<PathProfileInfo>();
80218885Sdim
81218885Sdim  // setup a data structure to map path edges which index an
82218885Sdim  // array of edge counters
83218885Sdim  NestedBlockToIndexMap arrayMap;
84218885Sdim  unsigned i = 0;
85218885Sdim  for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) {
86218885Sdim    if (F->isDeclaration()) continue;
87218885Sdim
88218885Sdim    arrayMap[0][F->begin()][0] = i++;
89218885Sdim
90218885Sdim    for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) {
91218885Sdim      TerminatorInst *TI = BB->getTerminator();
92218885Sdim
93218885Sdim      unsigned duplicate = 0;
94218885Sdim      BasicBlock* prev = 0;
95218885Sdim      for (unsigned s = 0, e = TI->getNumSuccessors(); s != e;
96218885Sdim           prev = TI->getSuccessor(s), ++s) {
97218885Sdim        if (prev == TI->getSuccessor(s))
98218885Sdim          duplicate++;
99218885Sdim        else duplicate = 0;
100218885Sdim
101218885Sdim        arrayMap[BB][TI->getSuccessor(s)][duplicate] = i++;
102218885Sdim      }
103218885Sdim    }
104218885Sdim  }
105218885Sdim
106218885Sdim  std::vector<unsigned> edgeArray(i);
107218885Sdim
108218885Sdim  // iterate through each path and increment the edge counters as needed
109218885Sdim  for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) {
110218885Sdim    if (F->isDeclaration()) continue;
111218885Sdim
112218885Sdim    pathProfileInfo.setCurrentFunction(F);
113218885Sdim
114218885Sdim    DEBUG(dbgs() << "function '" << F->getName() << "' ran "
115218885Sdim          << pathProfileInfo.pathsRun()
116218885Sdim          << "/" << pathProfileInfo.getPotentialPathCount()
117218885Sdim          << " potential paths\n");
118218885Sdim
119218885Sdim    for( ProfilePathIterator nextPath = pathProfileInfo.pathBegin(),
120218885Sdim           endPath = pathProfileInfo.pathEnd();
121218885Sdim         nextPath != endPath; nextPath++ ) {
122218885Sdim      ProfilePath* currentPath = nextPath->second;
123218885Sdim
124218885Sdim      ProfilePathEdgeVector* pev = currentPath->getPathEdges();
125218885Sdim      DEBUG(dbgs () << "path #" << currentPath->getNumber() << ": "
126218885Sdim            << currentPath->getCount() << "\n");
127221345Sdim      // setup the entry edge (normally path profiling doesn't care about this)
128218885Sdim      if (currentPath->getFirstBlockInPath() == &F->getEntryBlock())
129218885Sdim        edgeArray[arrayMap[0][currentPath->getFirstBlockInPath()][0]]
130218885Sdim          += currentPath->getCount();
131218885Sdim
132218885Sdim      for( ProfilePathEdgeIterator nextEdge = pev->begin(),
133218885Sdim             endEdge = pev->end(); nextEdge != endEdge; nextEdge++ ) {
134218885Sdim        if (nextEdge != pev->begin())
135218885Sdim          DEBUG(dbgs() << " :: ");
136218885Sdim
137218885Sdim        BasicBlock* source = nextEdge->getSource();
138218885Sdim        BasicBlock* target = nextEdge->getTarget();
139218885Sdim        unsigned duplicateNumber = nextEdge->getDuplicateNumber();
140218885Sdim        DEBUG(dbgs () << source->getNameStr() << " --{" << duplicateNumber
141218885Sdim              << "}--> " << target->getNameStr());
142218885Sdim
143218885Sdim        // Ensure all the referenced edges exist
144218885Sdim        // TODO: make this a separate function
145218885Sdim        if( !arrayMap.count(source) ) {
146218885Sdim          errs() << "  error [" << F->getNameStr() << "()]: source '"
147218885Sdim                 << source->getNameStr()
148218885Sdim                 << "' does not exist in the array map.\n";
149218885Sdim        } else if( !arrayMap[source].count(target) ) {
150218885Sdim          errs() << "  error [" << F->getNameStr() << "()]: target '"
151218885Sdim                 << target->getNameStr()
152218885Sdim                 << "' does not exist in the array map.\n";
153218885Sdim        } else if( !arrayMap[source][target].count(duplicateNumber) ) {
154218885Sdim          errs() << "  error [" << F->getNameStr() << "()]: edge "
155218885Sdim                 << source->getNameStr() << " -> " << target->getNameStr()
156218885Sdim                 << " duplicate number " << duplicateNumber
157218885Sdim                 << " does not exist in the array map.\n";
158218885Sdim        } else {
159218885Sdim          edgeArray[arrayMap[source][target][duplicateNumber]]
160218885Sdim            += currentPath->getCount();
161218885Sdim        }
162218885Sdim      }
163218885Sdim
164218885Sdim      DEBUG(errs() << "\n");
165218885Sdim
166218885Sdim      delete pev;
167218885Sdim    }
168218885Sdim  }
169218885Sdim
170218885Sdim  std::string errorInfo;
171218885Sdim  std::string filename = EdgeProfileFilename;
172218885Sdim
173218885Sdim  // Open a handle to the file
174218885Sdim  FILE* edgeFile = fopen(filename.c_str(),"wb");
175218885Sdim
176218885Sdim  if (!edgeFile) {
177218885Sdim    errs() << "error: unable to open file '" << filename << "' for output.\n";
178218885Sdim    return false;
179218885Sdim  }
180218885Sdim
181218885Sdim  errs() << "Generating edge profile '" << filename << "' ...\n";
182218885Sdim
183218885Sdim  // write argument info
184218885Sdim  unsigned type = ArgumentInfo;
185218885Sdim  unsigned num = pathProfileInfo.argList.size();
186218885Sdim  int zeros = 0;
187218885Sdim
188218885Sdim  fwrite(&type,sizeof(unsigned),1,edgeFile);
189218885Sdim  fwrite(&num,sizeof(unsigned),1,edgeFile);
190218885Sdim  fwrite(pathProfileInfo.argList.c_str(),1,num,edgeFile);
191218885Sdim  if (num&3)
192218885Sdim    fwrite(&zeros, 1, 4-(num&3), edgeFile);
193218885Sdim
194218885Sdim  type = EdgeInfo;
195218885Sdim  num = edgeArray.size();
196218885Sdim  fwrite(&type,sizeof(unsigned),1,edgeFile);
197218885Sdim  fwrite(&num,sizeof(unsigned),1,edgeFile);
198218885Sdim
199218885Sdim  // write each edge to the file
200218885Sdim  for( std::vector<unsigned>::iterator s = edgeArray.begin(),
201218885Sdim         e = edgeArray.end(); s != e; s++)
202218885Sdim    fwrite(&*s, sizeof (unsigned), 1, edgeFile);
203218885Sdim
204218885Sdim  fclose (edgeFile);
205218885Sdim
206218885Sdim  return true;
207218885Sdim}
208