Andreas Neustifter | e7ddcfd | 2009-09-01 08:48:42 +0000 | [diff] [blame] | 1 | //===- 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> |
| 22 | using namespace llvm; |
| 23 | |
| 24 | static bool DisableAssertions = false; |
| 25 | static cl::opt<bool,true> |
| 26 | ProfileVerifierDisableAssertions("profile-verifier-noassert", |
| 27 | cl::location(DisableAssertions), cl::desc("Disable assertions")); |
| 28 | bool PrintedDebugTree = false; |
| 29 | |
| 30 | namespace { |
| 31 | class VISIBILITY_HIDDEN ProfileVerifierPass : public FunctionPass { |
| 32 | ProfileInfo *PI; |
| 33 | std::set<const BasicBlock*> BBisVisited; |
| 34 | #ifndef NDEBUG |
| 35 | std::set<const BasicBlock*> BBisPrinted; |
| 36 | void debugEntry(const BasicBlock* BB, double w, double inw, int inc, |
| 37 | double outw, int outc, double d); |
| 38 | void printDebugInfo(const BasicBlock *BB); |
| 39 | #endif |
| 40 | public: |
| 41 | static char ID; // Class identification, replacement for typeinfo |
| 42 | |
| 43 | explicit ProfileVerifierPass () : FunctionPass(&ID) { |
| 44 | DisableAssertions = ProfileVerifierDisableAssertions; |
| 45 | } |
| 46 | |
| 47 | void getAnalysisUsage(AnalysisUsage &AU) const { |
| 48 | AU.setPreservesAll(); |
| 49 | AU.addRequired<ProfileInfo>(); |
| 50 | } |
| 51 | |
| 52 | const char *getPassName() const { |
| 53 | return "Profiling information verifier"; |
| 54 | } |
| 55 | |
| 56 | /// run - Verify the profile information. |
| 57 | bool runOnFunction(Function &F); |
| 58 | void recurseBasicBlock(const BasicBlock *BB); |
| 59 | }; |
| 60 | } // End of anonymous namespace |
| 61 | |
| 62 | char ProfileVerifierPass::ID = 0; |
| 63 | static RegisterPass<ProfileVerifierPass> |
| 64 | X("profile-verifier", "Verify profiling information", false, true); |
| 65 | |
| 66 | namespace llvm { |
| 67 | FunctionPass *createProfileVerifierPass() { |
| 68 | return new ProfileVerifierPass(); |
| 69 | } |
| 70 | } |
| 71 | |
| 72 | #ifndef NDEBUG |
| 73 | void ProfileVerifierPass::printDebugInfo(const BasicBlock *BB) { |
| 74 | |
| 75 | if (BBisPrinted.find(BB) != BBisPrinted.end()) return; |
| 76 | |
| 77 | double BBWeight = PI->getExecutionCount(BB); |
| 78 | if (BBWeight == ProfileInfo::MissingValue) { BBWeight = 0; } |
| 79 | double inWeight = 0; |
| 80 | int inCount = 0; |
| 81 | std::set<const BasicBlock*> ProcessedPreds; |
| 82 | for ( pred_const_iterator bbi = pred_begin(BB), bbe = pred_end(BB); |
| 83 | bbi != bbe; ++bbi ) { |
| 84 | if (ProcessedPreds.insert(*bbi).second) { |
| 85 | double EdgeWeight = PI->getEdgeWeight(PI->getEdge(*bbi,BB)); |
| 86 | if (EdgeWeight == ProfileInfo::MissingValue) { EdgeWeight = 0; } |
| 87 | DEBUG(errs()<<"calculated in-edge ("<<(*bbi)->getNameStr()<<","<<BB->getNameStr() |
| 88 | <<"): "<<EdgeWeight<<"\n"); |
| 89 | inWeight += EdgeWeight; |
| 90 | inCount++; |
| 91 | } |
| 92 | } |
| 93 | double outWeight = 0; |
| 94 | int outCount = 0; |
| 95 | std::set<const BasicBlock*> ProcessedSuccs; |
| 96 | for ( succ_const_iterator bbi = succ_begin(BB), bbe = succ_end(BB); |
| 97 | bbi != bbe; ++bbi ) { |
| 98 | if (ProcessedSuccs.insert(*bbi).second) { |
| 99 | double EdgeWeight = PI->getEdgeWeight(PI->getEdge(BB,*bbi)); |
| 100 | if (EdgeWeight == ProfileInfo::MissingValue) { EdgeWeight = 0; } |
| 101 | DEBUG(errs()<<"calculated out-edge ("<<BB->getNameStr()<<","<<(*bbi)->getNameStr() |
| 102 | <<"): "<<EdgeWeight<<"\n"); |
| 103 | outWeight += EdgeWeight; |
| 104 | outCount++; |
| 105 | } |
| 106 | } |
| 107 | DEBUG(errs()<<"Block "<<BB->getNameStr()<<" in "<<BB->getParent()->getNameStr() |
| 108 | <<",BBWeight="<<BBWeight<<",inWeight="<<inWeight<<",inCount="<<inCount |
| 109 | <<",outWeight="<<outWeight<<",outCount"<<outCount<<"\n"); |
| 110 | |
| 111 | // mark as visited and recurse into subnodes |
| 112 | BBisPrinted.insert(BB); |
| 113 | for ( succ_const_iterator bbi = succ_begin(BB), bbe = succ_end(BB); |
| 114 | bbi != bbe; ++bbi ) { |
| 115 | printDebugInfo(*bbi); |
| 116 | } |
| 117 | } |
| 118 | |
| 119 | void ProfileVerifierPass::debugEntry (const BasicBlock* BB, double w, |
| 120 | double inw, int inc, double outw, int |
| 121 | outc, double d) { |
| 122 | DEBUG(errs()<<"TROUBLE: Block "<<BB->getNameStr()<<" in "<<BB->getParent()->getNameStr() |
| 123 | <<",BBWeight="<<w<<",inWeight="<<inw<<",inCount="<<inc<<",outWeight=" |
| 124 | <<outw<<",outCount"<<outc<<"\n"); |
| 125 | DEBUG(errs()<<"DELTA:"<<d<<"\n"); |
| 126 | if (!PrintedDebugTree) { |
| 127 | PrintedDebugTree = true; |
| 128 | printDebugInfo(&(BB->getParent()->getEntryBlock())); |
| 129 | } |
| 130 | } |
| 131 | #endif |
| 132 | |
| 133 | // compare with relative error |
| 134 | static bool dcmp(double A, double B) { |
| 135 | double maxRelativeError = 0.0000001; |
| 136 | if (A == B) |
| 137 | return true; |
| 138 | double relativeError; |
| 139 | if (fabs(B) > fabs(A)) |
| 140 | relativeError = fabs((A - B) / B); |
| 141 | else |
| 142 | relativeError = fabs((A - B) / A); |
| 143 | if (relativeError <= maxRelativeError) return true; |
| 144 | return false; |
| 145 | } |
| 146 | |
| 147 | #define CHECK(C,M) \ |
| 148 | if (C) { \ |
| 149 | if (DisableAssertions) { errs()<<(M)<<"\n"; } else { assert((!(C)) && (M)); } \ |
| 150 | } |
| 151 | |
| 152 | #define CHECKDEBUG(C,M,D) \ |
| 153 | if (C) { \ |
| 154 | DEBUG(debugEntry(BB, BBWeight, inWeight, inCount, \ |
| 155 | outWeight, outCount, (D))); \ |
| 156 | if (DisableAssertions) { errs()<<(M)<<"\n"; } else { assert((!(C)) && (M)); } \ |
| 157 | } |
| 158 | |
| 159 | void ProfileVerifierPass::recurseBasicBlock(const BasicBlock *BB) { |
| 160 | |
| 161 | if (BBisVisited.find(BB) != BBisVisited.end()) return; |
| 162 | |
| 163 | double inWeight = 0; |
| 164 | int inCount = 0; |
| 165 | std::set<const BasicBlock*> ProcessedPreds; |
| 166 | for ( pred_const_iterator bbi = pred_begin(BB), bbe = pred_end(BB); |
| 167 | bbi != bbe; ++bbi ) { |
| 168 | if (ProcessedPreds.insert(*bbi).second) { |
| 169 | double EdgeWeight = PI->getEdgeWeight(PI->getEdge(*bbi,BB)); |
| 170 | CHECK(EdgeWeight == ProfileInfo::MissingValue, |
| 171 | "ASSERT:Edge has missing value"); |
| 172 | inWeight += EdgeWeight; inCount++; |
| 173 | } |
| 174 | } |
| 175 | |
| 176 | double outWeight = 0; |
| 177 | int outCount = 0; |
| 178 | std::set<const BasicBlock*> ProcessedSuccs; |
| 179 | for ( succ_const_iterator bbi = succ_begin(BB), bbe = succ_end(BB); |
| 180 | bbi != bbe; ++bbi ) { |
| 181 | if (ProcessedSuccs.insert(*bbi).second) { |
| 182 | double EdgeWeight = PI->getEdgeWeight(PI->getEdge(BB,*bbi)); |
| 183 | CHECK(EdgeWeight == ProfileInfo::MissingValue, |
| 184 | "ASSERT:Edge has missing value"); |
| 185 | outWeight += EdgeWeight; outCount++; |
| 186 | } |
| 187 | } |
| 188 | |
| 189 | double BBWeight = PI->getExecutionCount(BB); |
| 190 | CHECKDEBUG(BBWeight == ProfileInfo::MissingValue, |
| 191 | "ASSERT:BasicBlock has missing value",-1); |
| 192 | |
| 193 | if (inCount > 0) { |
| 194 | CHECKDEBUG(!dcmp(inWeight,BBWeight), |
| 195 | "ASSERT:inWeight and BBWeight do not match",inWeight-BBWeight); |
| 196 | } |
| 197 | if (outCount > 0) { |
| 198 | CHECKDEBUG(!dcmp(outWeight,BBWeight), |
| 199 | "ASSERT:outWeight and BBWeight do not match",outWeight-BBWeight); |
| 200 | } |
| 201 | |
| 202 | // mark as visited and recurse into subnodes |
| 203 | BBisVisited.insert(BB); |
| 204 | for ( succ_const_iterator bbi = succ_begin(BB), bbe = succ_end(BB); |
| 205 | bbi != bbe; ++bbi ) { |
| 206 | recurseBasicBlock(*bbi); |
| 207 | } |
| 208 | } |
| 209 | |
| 210 | bool ProfileVerifierPass::runOnFunction(Function &F) { |
| 211 | PI = &getAnalysis<ProfileInfo>(); |
| 212 | |
| 213 | if (PI->getExecutionCount(&F) == ProfileInfo::MissingValue) { |
| 214 | DEBUG(errs()<<"Function "<<F.getNameStr()<<" has no profile\n"); |
| 215 | return false; |
| 216 | } |
| 217 | |
| 218 | PrintedDebugTree = false; |
| 219 | BBisVisited.clear(); |
| 220 | |
| 221 | const BasicBlock *entry = &F.getEntryBlock(); |
| 222 | recurseBasicBlock(entry); |
| 223 | |
| 224 | if (!DisableAssertions) |
| 225 | assert((PI->getExecutionCount(&F)==PI->getExecutionCount(entry)) && |
| 226 | "Function count and entry block count do not match"); |
| 227 | return false; |
| 228 | } |