1 //===- PathProfileVerifier.cpp --------------------------------*- C++ -*---===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This verifier derives an edge profile file from current path profile
13 //===----------------------------------------------------------------------===//
14 #define DEBUG_TYPE "path-profile-verifier"
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/Debug.h"
22 #include "llvm/Support/CommandLine.h"
23 #include "llvm/Support/raw_ostream.h"
30 class PathProfileVerifier
: public ModulePass
{
32 bool runOnModule(Module
&M
);
35 static char ID
; // Pass identification, replacement for typeid
36 PathProfileVerifier() : ModulePass(ID
) {
37 initializePathProfileVerifierPass(*PassRegistry::getPassRegistry());
41 virtual const char *getPassName() const {
42 return "Path Profiler Verifier";
45 // The verifier requires the path profile and edge profile.
46 virtual void getAnalysisUsage(AnalysisUsage
& AU
) const;
50 static cl::opt
<std::string
>
51 EdgeProfileFilename("path-profile-verifier-file",
52 cl::init("edgefrompath.llvmprof.out"),
53 cl::value_desc("filename"),
54 cl::desc("Edge profile file generated by -path-profile-verifier"),
57 char PathProfileVerifier::ID
= 0;
58 INITIALIZE_PASS(PathProfileVerifier
, "path-profile-verifier",
59 "Compare the path profile derived edge profile against the "
60 "edge profile.", true, true)
62 ModulePass
*llvm::createPathProfileVerifierPass() {
63 return new PathProfileVerifier();
66 // The verifier requires the path profile and edge profile.
67 void PathProfileVerifier::getAnalysisUsage(AnalysisUsage
& AU
) const {
68 AU
.addRequired
<PathProfileInfo
>();
69 AU
.addPreserved
<PathProfileInfo
>();
72 typedef std::map
<unsigned, unsigned> DuplicateToIndexMap
;
73 typedef std::map
<BasicBlock
*,DuplicateToIndexMap
> BlockToDuplicateMap
;
74 typedef std::map
<BasicBlock
*,BlockToDuplicateMap
> NestedBlockToIndexMap
;
76 // the verifier iterates through each path to gather the total
77 // number of edge frequencies
78 bool PathProfileVerifier::runOnModule (Module
&M
) {
79 PathProfileInfo
& pathProfileInfo
= getAnalysis
<PathProfileInfo
>();
81 // setup a data structure to map path edges which index an
82 // array of edge counters
83 NestedBlockToIndexMap arrayMap
;
85 for (Module::iterator F
= M
.begin(), E
= M
.end(); F
!= E
; ++F
) {
86 if (F
->isDeclaration()) continue;
88 arrayMap
[0][F
->begin()][0] = i
++;
90 for (Function::iterator BB
= F
->begin(), E
= F
->end(); BB
!= E
; ++BB
) {
91 TerminatorInst
*TI
= BB
->getTerminator();
93 unsigned duplicate
= 0;
95 for (unsigned s
= 0, e
= TI
->getNumSuccessors(); s
!= e
;
96 prev
= TI
->getSuccessor(s
), ++s
) {
97 if (prev
== TI
->getSuccessor(s
))
101 arrayMap
[BB
][TI
->getSuccessor(s
)][duplicate
] = i
++;
106 std::vector
<unsigned> edgeArray(i
);
108 // iterate through each path and increment the edge counters as needed
109 for (Module::iterator F
= M
.begin(), E
= M
.end(); F
!= E
; ++F
) {
110 if (F
->isDeclaration()) continue;
112 pathProfileInfo
.setCurrentFunction(F
);
114 DEBUG(dbgs() << "function '" << F
->getName() << "' ran "
115 << pathProfileInfo
.pathsRun()
116 << "/" << pathProfileInfo
.getPotentialPathCount()
117 << " potential paths\n");
119 for( ProfilePathIterator nextPath
= pathProfileInfo
.pathBegin(),
120 endPath
= pathProfileInfo
.pathEnd();
121 nextPath
!= endPath
; nextPath
++ ) {
122 ProfilePath
* currentPath
= nextPath
->second
;
124 ProfilePathEdgeVector
* pev
= currentPath
->getPathEdges();
125 DEBUG(dbgs () << "path #" << currentPath
->getNumber() << ": "
126 << currentPath
->getCount() << "\n");
127 // setup the entry edge (normally path profiling doesn't care about this)
128 if (currentPath
->getFirstBlockInPath() == &F
->getEntryBlock())
129 edgeArray
[arrayMap
[0][currentPath
->getFirstBlockInPath()][0]]
130 += currentPath
->getCount();
132 for( ProfilePathEdgeIterator nextEdge
= pev
->begin(),
133 endEdge
= pev
->end(); nextEdge
!= endEdge
; nextEdge
++ ) {
134 if (nextEdge
!= pev
->begin())
135 DEBUG(dbgs() << " :: ");
137 BasicBlock
* source
= nextEdge
->getSource();
138 BasicBlock
* target
= nextEdge
->getTarget();
139 unsigned duplicateNumber
= nextEdge
->getDuplicateNumber();
140 DEBUG(dbgs () << source
->getNameStr() << " --{" << duplicateNumber
141 << "}--> " << target
->getNameStr());
143 // Ensure all the referenced edges exist
144 // TODO: make this a separate function
145 if( !arrayMap
.count(source
) ) {
146 errs() << " error [" << F
->getNameStr() << "()]: source '"
147 << source
->getNameStr()
148 << "' does not exist in the array map.\n";
149 } else if( !arrayMap
[source
].count(target
) ) {
150 errs() << " error [" << F
->getNameStr() << "()]: target '"
151 << target
->getNameStr()
152 << "' does not exist in the array map.\n";
153 } else if( !arrayMap
[source
][target
].count(duplicateNumber
) ) {
154 errs() << " error [" << F
->getNameStr() << "()]: edge "
155 << source
->getNameStr() << " -> " << target
->getNameStr()
156 << " duplicate number " << duplicateNumber
157 << " does not exist in the array map.\n";
159 edgeArray
[arrayMap
[source
][target
][duplicateNumber
]]
160 += currentPath
->getCount();
164 DEBUG(errs() << "\n");
170 std::string errorInfo
;
171 std::string filename
= EdgeProfileFilename
;
173 // Open a handle to the file
174 FILE* edgeFile
= fopen(filename
.c_str(),"wb");
177 errs() << "error: unable to open file '" << filename
<< "' for output.\n";
181 errs() << "Generating edge profile '" << filename
<< "' ...\n";
183 // write argument info
184 unsigned type
= ArgumentInfo
;
185 unsigned num
= pathProfileInfo
.argList
.size();
188 fwrite(&type
,sizeof(unsigned),1,edgeFile
);
189 fwrite(&num
,sizeof(unsigned),1,edgeFile
);
190 fwrite(pathProfileInfo
.argList
.c_str(),1,num
,edgeFile
);
192 fwrite(&zeros
, 1, 4-(num
&3), edgeFile
);
195 num
= edgeArray
.size();
196 fwrite(&type
,sizeof(unsigned),1,edgeFile
);
197 fwrite(&num
,sizeof(unsigned),1,edgeFile
);
199 // write each edge to the file
200 for( std::vector
<unsigned>::iterator s
= edgeArray
.begin(),
201 e
= edgeArray
.end(); s
!= e
; s
++)
202 fwrite(&*s
, sizeof (unsigned), 1, edgeFile
);