Add a small missed optimization: turn X == C ? X : Y into X == C ? C : Y. This
[llvm/stm8.git] / lib / Analysis / PathProfileVerifier.cpp
blobc549773142073fe210c2a819378bf78a3e3a200b
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
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"
25 #include <stdio.h>
27 using namespace llvm;
29 namespace {
30 class PathProfileVerifier : public ModulePass {
31 private:
32 bool runOnModule(Module &M);
34 public:
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"),
55 cl::Hidden);
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;
84 unsigned i = 0;
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;
94 BasicBlock* prev = 0;
95 for (unsigned s = 0, e = TI->getNumSuccessors(); s != e;
96 prev = TI->getSuccessor(s), ++s) {
97 if (prev == TI->getSuccessor(s))
98 duplicate++;
99 else duplicate = 0;
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 doens'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";
158 } else {
159 edgeArray[arrayMap[source][target][duplicateNumber]]
160 += currentPath->getCount();
164 DEBUG(errs() << "\n");
166 delete pev;
170 std::string errorInfo;
171 std::string filename = EdgeProfileFilename;
173 // Open a handle to the file
174 FILE* edgeFile = fopen(filename.c_str(),"wb");
176 if (!edgeFile) {
177 errs() << "error: unable to open file '" << filename << "' for output.\n";
178 return false;
181 errs() << "Generating edge profile '" << filename << "' ...\n";
183 // write argument info
184 unsigned type = ArgumentInfo;
185 unsigned num = pathProfileInfo.argList.size();
186 int zeros = 0;
188 fwrite(&type,sizeof(unsigned),1,edgeFile);
189 fwrite(&num,sizeof(unsigned),1,edgeFile);
190 fwrite(pathProfileInfo.argList.c_str(),1,num,edgeFile);
191 if (num&3)
192 fwrite(&zeros, 1, 4-(num&3), edgeFile);
194 type = EdgeInfo;
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);
204 fclose (edgeFile);
206 return true;