blob: 0cb75a2a07d3354f2e291e2799bdcf643d03ad6c [file] [log] [blame]
Andreas Neustiftere7ddcfd2009-09-01 08:48:42 +00001//===- ProfileVerifierPass.cpp - LLVM Pass to estimate 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 pass that checks profiling information for
11// plausibility.
12//
13//===----------------------------------------------------------------------===//
14#define DEBUG_TYPE "profile-verifier"
15#include "llvm/Pass.h"
16#include "llvm/Analysis/ProfileInfo.h"
17#include "llvm/Support/CommandLine.h"
18#include "llvm/Support/CFG.h"
19#include "llvm/Support/raw_ostream.h"
20#include "llvm/Support/Debug.h"
21#include <set>
22using namespace llvm;
23
Andreas Neustiftere7ddcfd2009-09-01 08:48:42 +000024static cl::opt<bool,true>
25ProfileVerifierDisableAssertions("profile-verifier-noassert",
Andreas Neustiftere8d372e2009-09-04 17:15:10 +000026 cl::desc("Disable assertions"));
Andreas Neustiftere7ddcfd2009-09-01 08:48:42 +000027
28namespace {
29 class VISIBILITY_HIDDEN ProfileVerifierPass : public FunctionPass {
Andreas Neustiftere8d372e2009-09-04 17:15:10 +000030
31 struct DetailedBlockInfo {
32 const BasicBlock *BB;
33 double BBWeight;
34 double inWeight;
35 int inCount;
36 double outWeight;
37 int outCount;
38 };
39
Andreas Neustiftere7ddcfd2009-09-01 08:48:42 +000040 ProfileInfo *PI;
41 std::set<const BasicBlock*> BBisVisited;
Andreas Neustiftere8d372e2009-09-04 17:15:10 +000042 bool DisableAssertions;
43
44 // When debugging is enabled, the verifier prints a whole slew of debug
45 // information, otherwise its just the assert. These are all the helper
46 // functions.
47 bool PrintedDebugTree;
Andreas Neustiftere7ddcfd2009-09-01 08:48:42 +000048 std::set<const BasicBlock*> BBisPrinted;
Andreas Neustiftere8d372e2009-09-04 17:15:10 +000049 void debugEntry(DetailedBlockInfo*);
Andreas Neustiftere7ddcfd2009-09-01 08:48:42 +000050 void printDebugInfo(const BasicBlock *BB);
Andreas Neustiftere8d372e2009-09-04 17:15:10 +000051
Andreas Neustiftere7ddcfd2009-09-01 08:48:42 +000052 public:
53 static char ID; // Class identification, replacement for typeinfo
54
Andreas Neustiftere8d372e2009-09-04 17:15:10 +000055 explicit ProfileVerifierPass (bool da = false) : FunctionPass(&ID),
56 DisableAssertions(da) {
Andreas Neustiftere7ddcfd2009-09-01 08:48:42 +000057 }
58
59 void getAnalysisUsage(AnalysisUsage &AU) const {
60 AU.setPreservesAll();
61 AU.addRequired<ProfileInfo>();
62 }
63
64 const char *getPassName() const {
65 return "Profiling information verifier";
66 }
67
68 /// run - Verify the profile information.
69 bool runOnFunction(Function &F);
70 void recurseBasicBlock(const BasicBlock *BB);
Andreas Neustiftere8d372e2009-09-04 17:15:10 +000071
72 double ReadOrAssert(ProfileInfo::Edge);
73 void CheckValue(bool, const char*, DetailedBlockInfo*);
Andreas Neustiftere7ddcfd2009-09-01 08:48:42 +000074 };
75} // End of anonymous namespace
76
77char ProfileVerifierPass::ID = 0;
78static RegisterPass<ProfileVerifierPass>
79X("profile-verifier", "Verify profiling information", false, true);
80
81namespace llvm {
82 FunctionPass *createProfileVerifierPass() {
Andreas Neustiftere8d372e2009-09-04 17:15:10 +000083 return new ProfileVerifierPass(ProfileVerifierDisableAssertions);
Andreas Neustiftere7ddcfd2009-09-01 08:48:42 +000084 }
85}
86
Andreas Neustiftere7ddcfd2009-09-01 08:48:42 +000087void ProfileVerifierPass::printDebugInfo(const BasicBlock *BB) {
88
89 if (BBisPrinted.find(BB) != BBisPrinted.end()) return;
90
91 double BBWeight = PI->getExecutionCount(BB);
92 if (BBWeight == ProfileInfo::MissingValue) { BBWeight = 0; }
93 double inWeight = 0;
94 int inCount = 0;
95 std::set<const BasicBlock*> ProcessedPreds;
96 for ( pred_const_iterator bbi = pred_begin(BB), bbe = pred_end(BB);
97 bbi != bbe; ++bbi ) {
98 if (ProcessedPreds.insert(*bbi).second) {
99 double EdgeWeight = PI->getEdgeWeight(PI->getEdge(*bbi,BB));
100 if (EdgeWeight == ProfileInfo::MissingValue) { EdgeWeight = 0; }
Andreas Neustiftere8d372e2009-09-04 17:15:10 +0000101 errs()<<"calculated in-edge ("<<(*bbi)->getNameStr()<<","<<BB->getNameStr()
102 <<"): "<<EdgeWeight<<"\n";
Andreas Neustiftere7ddcfd2009-09-01 08:48:42 +0000103 inWeight += EdgeWeight;
104 inCount++;
105 }
106 }
107 double outWeight = 0;
108 int outCount = 0;
109 std::set<const BasicBlock*> ProcessedSuccs;
110 for ( succ_const_iterator bbi = succ_begin(BB), bbe = succ_end(BB);
111 bbi != bbe; ++bbi ) {
112 if (ProcessedSuccs.insert(*bbi).second) {
113 double EdgeWeight = PI->getEdgeWeight(PI->getEdge(BB,*bbi));
114 if (EdgeWeight == ProfileInfo::MissingValue) { EdgeWeight = 0; }
Andreas Neustiftere8d372e2009-09-04 17:15:10 +0000115 errs()<<"calculated out-edge ("<<BB->getNameStr()<<","<<(*bbi)->getNameStr()
116 <<"): "<<EdgeWeight<<"\n";
Andreas Neustiftere7ddcfd2009-09-01 08:48:42 +0000117 outWeight += EdgeWeight;
118 outCount++;
119 }
120 }
Andreas Neustiftere8d372e2009-09-04 17:15:10 +0000121 errs()<<"Block "<<BB->getNameStr()<<" in "<<BB->getParent()->getNameStr()
122 <<",BBWeight="<<BBWeight<<",inWeight="<<inWeight<<",inCount="<<inCount
123 <<",outWeight="<<outWeight<<",outCount"<<outCount<<"\n";
Andreas Neustiftere7ddcfd2009-09-01 08:48:42 +0000124
125 // mark as visited and recurse into subnodes
126 BBisPrinted.insert(BB);
127 for ( succ_const_iterator bbi = succ_begin(BB), bbe = succ_end(BB);
128 bbi != bbe; ++bbi ) {
129 printDebugInfo(*bbi);
130 }
131}
132
Andreas Neustiftere8d372e2009-09-04 17:15:10 +0000133void ProfileVerifierPass::debugEntry (DetailedBlockInfo *DI) {
134 errs() << "TROUBLE: Block " << DI->BB->getNameStr() << " in "
135 << DI->BB->getParent()->getNameStr() << ":";
136 errs() << "BBWeight=" << DI->BBWeight << ",";
137 errs() << "inWeight=" << DI->inWeight << ",";
138 errs() << "inCount=" << DI->inCount << ",";
139 errs() << "outWeight=" << DI->outWeight << ",";
140 errs() << "outCount=" << DI->outCount << ",";
Andreas Neustiftere7ddcfd2009-09-01 08:48:42 +0000141 if (!PrintedDebugTree) {
142 PrintedDebugTree = true;
Andreas Neustiftere8d372e2009-09-04 17:15:10 +0000143 printDebugInfo(&(DI->BB->getParent()->getEntryBlock()));
Andreas Neustiftere7ddcfd2009-09-01 08:48:42 +0000144 }
145}
Andreas Neustiftere7ddcfd2009-09-01 08:48:42 +0000146
147// compare with relative error
Andreas Neustiftere8d372e2009-09-04 17:15:10 +0000148static bool Equals(double A, double B) {
Andreas Neustiftere7ddcfd2009-09-01 08:48:42 +0000149 double maxRelativeError = 0.0000001;
150 if (A == B)
151 return true;
152 double relativeError;
153 if (fabs(B) > fabs(A))
154 relativeError = fabs((A - B) / B);
155 else
156 relativeError = fabs((A - B) / A);
157 if (relativeError <= maxRelativeError) return true;
158 return false;
159}
160
Andreas Neustiftere8d372e2009-09-04 17:15:10 +0000161double ProfileVerifierPass::ReadOrAssert(ProfileInfo::Edge E) {
162 const char *Message = "ASSERT:Edge has missing value";
163 double EdgeWeight = PI->getEdgeWeight(E);
164 if (EdgeWeight == ProfileInfo::MissingValue) {
165 if (DisableAssertions) {
166 errs() << Message << "\n";
167 return 0;
168 } else {
169 assert(0 && Message);
Andreas Neustifter31dcbc32009-09-04 21:22:04 +0000170 return 0;
Andreas Neustiftere8d372e2009-09-04 17:15:10 +0000171 }
172 } else {
173 return EdgeWeight;
174 }
Andreas Neustiftere7ddcfd2009-09-01 08:48:42 +0000175}
176
Andreas Neustiftere8d372e2009-09-04 17:15:10 +0000177void ProfileVerifierPass::CheckValue(bool Error, const char *Message, DetailedBlockInfo *DI) {
178 if (Error) {
179 DEBUG(debugEntry(DI));
180 if (DisableAssertions) {
181 errs() << Message << "\n";
182 } else {
183 assert(0 && Message);
184 }
185 }
186 return;
Andreas Neustiftere7ddcfd2009-09-01 08:48:42 +0000187}
188
189void ProfileVerifierPass::recurseBasicBlock(const BasicBlock *BB) {
190
191 if (BBisVisited.find(BB) != BBisVisited.end()) return;
192
Andreas Neustiftere8d372e2009-09-04 17:15:10 +0000193 DetailedBlockInfo DI;
194 DI.BB = BB;
195 DI.outCount = DI.inCount = DI.inWeight = DI.outWeight = 0;
Andreas Neustiftere7ddcfd2009-09-01 08:48:42 +0000196 std::set<const BasicBlock*> ProcessedPreds;
197 for ( pred_const_iterator bbi = pred_begin(BB), bbe = pred_end(BB);
198 bbi != bbe; ++bbi ) {
199 if (ProcessedPreds.insert(*bbi).second) {
Andreas Neustiftere8d372e2009-09-04 17:15:10 +0000200 DI.inWeight += ReadOrAssert(PI->getEdge(*bbi,BB));
201 DI.inCount++;
Andreas Neustiftere7ddcfd2009-09-01 08:48:42 +0000202 }
203 }
204
Andreas Neustiftere7ddcfd2009-09-01 08:48:42 +0000205 std::set<const BasicBlock*> ProcessedSuccs;
206 for ( succ_const_iterator bbi = succ_begin(BB), bbe = succ_end(BB);
207 bbi != bbe; ++bbi ) {
208 if (ProcessedSuccs.insert(*bbi).second) {
Andreas Neustiftere8d372e2009-09-04 17:15:10 +0000209 DI.outWeight += ReadOrAssert(PI->getEdge(BB,*bbi));
210 DI.outCount++;
Andreas Neustiftere7ddcfd2009-09-01 08:48:42 +0000211 }
212 }
213
Andreas Neustiftere8d372e2009-09-04 17:15:10 +0000214 DI.BBWeight = PI->getExecutionCount(BB);
215 CheckValue(DI.BBWeight == ProfileInfo::MissingValue, "ASSERT:BasicBlock has missing value", &DI);
Andreas Neustiftere7ddcfd2009-09-01 08:48:42 +0000216
Andreas Neustiftere8d372e2009-09-04 17:15:10 +0000217 if (DI.inCount > 0) {
218 CheckValue(!Equals(DI.inWeight,DI.BBWeight), "ASSERT:inWeight and BBWeight do not match", &DI);
Andreas Neustiftere7ddcfd2009-09-01 08:48:42 +0000219 }
Andreas Neustiftere8d372e2009-09-04 17:15:10 +0000220 if (DI.outCount > 0) {
221 CheckValue(!Equals(DI.outWeight,DI.BBWeight), "ASSERT:outWeight and BBWeight do not match", &DI);
Andreas Neustiftere7ddcfd2009-09-01 08:48:42 +0000222 }
223
224 // mark as visited and recurse into subnodes
225 BBisVisited.insert(BB);
226 for ( succ_const_iterator bbi = succ_begin(BB), bbe = succ_end(BB);
227 bbi != bbe; ++bbi ) {
228 recurseBasicBlock(*bbi);
229 }
230}
231
232bool ProfileVerifierPass::runOnFunction(Function &F) {
233 PI = &getAnalysis<ProfileInfo>();
234
235 if (PI->getExecutionCount(&F) == ProfileInfo::MissingValue) {
236 DEBUG(errs()<<"Function "<<F.getNameStr()<<" has no profile\n");
237 return false;
238 }
239
240 PrintedDebugTree = false;
241 BBisVisited.clear();
242
243 const BasicBlock *entry = &F.getEntryBlock();
244 recurseBasicBlock(entry);
245
246 if (!DisableAssertions)
247 assert((PI->getExecutionCount(&F)==PI->getExecutionCount(entry)) &&
248 "Function count and entry block count do not match");
249 return false;
250}