• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===- PathProfileVerifier.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 verifier derives an edge profile file from current path profile
11 // information
12 //
13 //===----------------------------------------------------------------------===//
14 #define DEBUG_TYPE "path-profile-verifier"
15 
16 #include "llvm/Analysis/Passes.h"
17 #include "llvm/Analysis/PathProfileInfo.h"
18 #include "llvm/Analysis/ProfileInfoTypes.h"
19 #include "llvm/IR/Module.h"
20 #include "llvm/Pass.h"
21 #include "llvm/Support/CommandLine.h"
22 #include "llvm/Support/Debug.h"
23 #include "llvm/Support/raw_ostream.h"
24 #include <stdio.h>
25 
26 using namespace llvm;
27 
28 namespace {
29   class PathProfileVerifier : public ModulePass {
30   private:
31     bool runOnModule(Module &M);
32 
33   public:
34     static char ID; // Pass identification, replacement for typeid
PathProfileVerifier()35     PathProfileVerifier() : ModulePass(ID) {
36       initializePathProfileVerifierPass(*PassRegistry::getPassRegistry());
37     }
38 
39 
getPassName() const40     virtual const char *getPassName() const {
41       return "Path Profiler Verifier";
42     }
43 
44     // The verifier requires the path profile and edge profile.
45     virtual void getAnalysisUsage(AnalysisUsage& AU) const;
46   };
47 }
48 
49 static cl::opt<std::string>
50 EdgeProfileFilename("path-profile-verifier-file",
51   cl::init("edgefrompath.llvmprof.out"),
52   cl::value_desc("filename"),
53   cl::desc("Edge profile file generated by -path-profile-verifier"),
54   cl::Hidden);
55 
56 char PathProfileVerifier::ID = 0;
57 INITIALIZE_PASS(PathProfileVerifier, "path-profile-verifier",
58                 "Compare the path profile derived edge profile against the "
59                 "edge profile.", true, true)
60 
createPathProfileVerifierPass()61 ModulePass *llvm::createPathProfileVerifierPass() {
62   return new PathProfileVerifier();
63 }
64 
65 // The verifier requires the path profile and edge profile.
getAnalysisUsage(AnalysisUsage & AU) const66 void PathProfileVerifier::getAnalysisUsage(AnalysisUsage& AU) const {
67   AU.addRequired<PathProfileInfo>();
68   AU.addPreserved<PathProfileInfo>();
69 }
70 
71 typedef std::map<unsigned, unsigned> DuplicateToIndexMap;
72 typedef std::map<BasicBlock*,DuplicateToIndexMap> BlockToDuplicateMap;
73 typedef std::map<BasicBlock*,BlockToDuplicateMap> NestedBlockToIndexMap;
74 
75 // the verifier iterates through each path to gather the total
76 // number of edge frequencies
runOnModule(Module & M)77 bool PathProfileVerifier::runOnModule (Module &M) {
78   PathProfileInfo& pathProfileInfo = getAnalysis<PathProfileInfo>();
79 
80   // setup a data structure to map path edges which index an
81   // array of edge counters
82   NestedBlockToIndexMap arrayMap;
83   unsigned i = 0;
84   for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) {
85     if (F->isDeclaration()) continue;
86 
87     arrayMap[0][F->begin()][0] = i++;
88 
89     for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) {
90       TerminatorInst *TI = BB->getTerminator();
91 
92       unsigned duplicate = 0;
93       BasicBlock* prev = 0;
94       for (unsigned s = 0, e = TI->getNumSuccessors(); s != e;
95            prev = TI->getSuccessor(s), ++s) {
96         if (prev == TI->getSuccessor(s))
97           duplicate++;
98         else duplicate = 0;
99 
100         arrayMap[BB][TI->getSuccessor(s)][duplicate] = i++;
101       }
102     }
103   }
104 
105   std::vector<unsigned> edgeArray(i);
106 
107   // iterate through each path and increment the edge counters as needed
108   for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) {
109     if (F->isDeclaration()) continue;
110 
111     pathProfileInfo.setCurrentFunction(F);
112 
113     DEBUG(dbgs() << "function '" << F->getName() << "' ran "
114           << pathProfileInfo.pathsRun()
115           << "/" << pathProfileInfo.getPotentialPathCount()
116           << " potential paths\n");
117 
118     for( ProfilePathIterator nextPath = pathProfileInfo.pathBegin(),
119            endPath = pathProfileInfo.pathEnd();
120          nextPath != endPath; nextPath++ ) {
121       ProfilePath* currentPath = nextPath->second;
122 
123       ProfilePathEdgeVector* pev = currentPath->getPathEdges();
124       DEBUG(dbgs () << "path #" << currentPath->getNumber() << ": "
125             << currentPath->getCount() << "\n");
126       // setup the entry edge (normally path profiling doesn't care about this)
127       if (currentPath->getFirstBlockInPath() == &F->getEntryBlock())
128         edgeArray[arrayMap[0][currentPath->getFirstBlockInPath()][0]]
129           += currentPath->getCount();
130 
131       for( ProfilePathEdgeIterator nextEdge = pev->begin(),
132              endEdge = pev->end(); nextEdge != endEdge; nextEdge++ ) {
133         if (nextEdge != pev->begin())
134           DEBUG(dbgs() << " :: ");
135 
136         BasicBlock* source = nextEdge->getSource();
137         BasicBlock* target = nextEdge->getTarget();
138         unsigned duplicateNumber = nextEdge->getDuplicateNumber();
139         DEBUG(dbgs() << source->getName() << " --{" << duplicateNumber
140                      << "}--> " << target->getName());
141 
142         // Ensure all the referenced edges exist
143         // TODO: make this a separate function
144         if( !arrayMap.count(source) ) {
145           errs() << "  error [" << F->getName() << "()]: source '"
146                  << source->getName()
147                  << "' does not exist in the array map.\n";
148         } else if( !arrayMap[source].count(target) ) {
149           errs() << "  error [" << F->getName() << "()]: target '"
150                  << target->getName()
151                  << "' does not exist in the array map.\n";
152         } else if( !arrayMap[source][target].count(duplicateNumber) ) {
153           errs() << "  error [" << F->getName() << "()]: edge "
154                  << source->getName() << " -> " << target->getName()
155                  << " duplicate number " << duplicateNumber
156                  << " does not exist in the array map.\n";
157         } else {
158           edgeArray[arrayMap[source][target][duplicateNumber]]
159             += currentPath->getCount();
160         }
161       }
162 
163       DEBUG(errs() << "\n");
164 
165       delete pev;
166     }
167   }
168 
169   std::string errorInfo;
170   std::string filename = EdgeProfileFilename;
171 
172   // Open a handle to the file
173   FILE* edgeFile = fopen(filename.c_str(),"wb");
174 
175   if (!edgeFile) {
176     errs() << "error: unable to open file '" << filename << "' for output.\n";
177     return false;
178   }
179 
180   errs() << "Generating edge profile '" << filename << "' ...\n";
181 
182   // write argument info
183   unsigned type = ArgumentInfo;
184   unsigned num = pathProfileInfo.argList.size();
185   int zeros = 0;
186 
187   fwrite(&type,sizeof(unsigned),1,edgeFile);
188   fwrite(&num,sizeof(unsigned),1,edgeFile);
189   fwrite(pathProfileInfo.argList.c_str(),1,num,edgeFile);
190   if (num&3)
191     fwrite(&zeros, 1, 4-(num&3), edgeFile);
192 
193   type = EdgeInfo;
194   num = edgeArray.size();
195   fwrite(&type,sizeof(unsigned),1,edgeFile);
196   fwrite(&num,sizeof(unsigned),1,edgeFile);
197 
198   // write each edge to the file
199   for( std::vector<unsigned>::iterator s = edgeArray.begin(),
200          e = edgeArray.end(); s != e; s++)
201     fwrite(&*s, sizeof (unsigned), 1, edgeFile);
202 
203   fclose (edgeFile);
204 
205   return true;
206 }
207