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/Instructions.h" 16 #include "llvm/Module.h" 17 #include "llvm/Pass.h" 18 #include "llvm/Analysis/ProfileInfo.h" 19 #include "llvm/Support/CommandLine.h" 20 #include "llvm/Support/CallSite.h" 21 #include "llvm/Support/CFG.h" 22 #include "llvm/Support/InstIterator.h" 23 #include "llvm/Support/raw_ostream.h" 24 #include "llvm/Support/Format.h" 25 #include "llvm/Support/Debug.h" 26 #include <set> 27 using namespace llvm; 28 29 static cl::opt<bool,false> 30 ProfileVerifierDisableAssertions("profile-verifier-noassert", 31 cl::desc("Disable assertions")); 32 33 namespace llvm { 34 template<class FType, class BType> 35 class ProfileVerifierPassT : public FunctionPass { 36 37 struct DetailedBlockInfo { 38 const BType *BB; 39 double BBWeight; 40 double inWeight; 41 int inCount; 42 double outWeight; 43 int outCount; 44 }; 45 46 ProfileInfoT<FType, BType> *PI; 47 std::set<const BType*> BBisVisited; 48 std::set<const FType*> FisVisited; 49 bool DisableAssertions; 50 51 // When debugging is enabled, the verifier prints a whole slew of debug 52 // information, otherwise its just the assert. These are all the helper 53 // functions. 54 bool PrintedDebugTree; 55 std::set<const BType*> BBisPrinted; 56 void debugEntry(DetailedBlockInfo*); 57 void printDebugInfo(const BType *BB); 58 59 public: 60 static char ID; // Class identification, replacement for typeinfo 61 ProfileVerifierPassT()62 explicit ProfileVerifierPassT () : FunctionPass(ID) { 63 initializeProfileVerifierPassPass(*PassRegistry::getPassRegistry()); 64 DisableAssertions = ProfileVerifierDisableAssertions; 65 } ProfileVerifierPassT(bool da)66 explicit ProfileVerifierPassT (bool da) : FunctionPass(ID), 67 DisableAssertions(da) { 68 initializeProfileVerifierPassPass(*PassRegistry::getPassRegistry()); 69 } 70 getAnalysisUsage(AnalysisUsage & AU) const71 void getAnalysisUsage(AnalysisUsage &AU) const { 72 AU.setPreservesAll(); 73 AU.addRequired<ProfileInfoT<FType, BType> >(); 74 } 75 getPassName() const76 const char *getPassName() const { 77 return "Profiling information verifier"; 78 } 79 80 /// run - Verify the profile information. 81 bool runOnFunction(FType &F); 82 void recurseBasicBlock(const BType*); 83 84 bool exitReachable(const FType*); 85 double ReadOrAssert(typename ProfileInfoT<FType, BType>::Edge); 86 void CheckValue(bool, const char*, DetailedBlockInfo*); 87 }; 88 89 typedef ProfileVerifierPassT<Function, BasicBlock> ProfileVerifierPass; 90 91 template<class FType, class BType> printDebugInfo(const BType * BB)92 void ProfileVerifierPassT<FType, BType>::printDebugInfo(const BType *BB) { 93 94 if (BBisPrinted.find(BB) != BBisPrinted.end()) return; 95 96 double BBWeight = PI->getExecutionCount(BB); 97 if (BBWeight == ProfileInfoT<FType, BType>::MissingValue) { BBWeight = 0; } 98 double inWeight = 0; 99 int inCount = 0; 100 std::set<const BType*> ProcessedPreds; 101 for (const_pred_iterator bbi = pred_begin(BB), bbe = pred_end(BB); 102 bbi != bbe; ++bbi ) { 103 if (ProcessedPreds.insert(*bbi).second) { 104 typename ProfileInfoT<FType, BType>::Edge E = PI->getEdge(*bbi,BB); 105 double EdgeWeight = PI->getEdgeWeight(E); 106 if (EdgeWeight == ProfileInfoT<FType, BType>::MissingValue) { EdgeWeight = 0; } 107 dbgs() << "calculated in-edge " << E << ": " 108 << format("%20.20g",EdgeWeight) << "\n"; 109 inWeight += EdgeWeight; 110 inCount++; 111 } 112 } 113 double outWeight = 0; 114 int outCount = 0; 115 std::set<const BType*> ProcessedSuccs; 116 for ( succ_const_iterator bbi = succ_begin(BB), bbe = succ_end(BB); 117 bbi != bbe; ++bbi ) { 118 if (ProcessedSuccs.insert(*bbi).second) { 119 typename ProfileInfoT<FType, BType>::Edge E = PI->getEdge(BB,*bbi); 120 double EdgeWeight = PI->getEdgeWeight(E); 121 if (EdgeWeight == ProfileInfoT<FType, BType>::MissingValue) { EdgeWeight = 0; } 122 dbgs() << "calculated out-edge " << E << ": " 123 << format("%20.20g",EdgeWeight) << "\n"; 124 outWeight += EdgeWeight; 125 outCount++; 126 } 127 } 128 dbgs() << "Block " << BB->getNameStr() << " in " 129 << BB->getParent()->getNameStr() << ":" 130 << "BBWeight=" << format("%20.20g",BBWeight) << "," 131 << "inWeight=" << format("%20.20g",inWeight) << "," 132 << "inCount=" << inCount << "," 133 << "outWeight=" << format("%20.20g",outWeight) << "," 134 << "outCount" << outCount << "\n"; 135 136 // mark as visited and recurse into subnodes 137 BBisPrinted.insert(BB); 138 for ( succ_const_iterator bbi = succ_begin(BB), bbe = succ_end(BB); 139 bbi != bbe; ++bbi ) { 140 printDebugInfo(*bbi); 141 } 142 } 143 144 template<class FType, class BType> debugEntry(DetailedBlockInfo * DI)145 void ProfileVerifierPassT<FType, BType>::debugEntry (DetailedBlockInfo *DI) { 146 dbgs() << "TROUBLE: Block " << DI->BB->getNameStr() << " in " 147 << DI->BB->getParent()->getNameStr() << ":" 148 << "BBWeight=" << format("%20.20g",DI->BBWeight) << "," 149 << "inWeight=" << format("%20.20g",DI->inWeight) << "," 150 << "inCount=" << DI->inCount << "," 151 << "outWeight=" << format("%20.20g",DI->outWeight) << "," 152 << "outCount=" << DI->outCount << "\n"; 153 if (!PrintedDebugTree) { 154 PrintedDebugTree = true; 155 printDebugInfo(&(DI->BB->getParent()->getEntryBlock())); 156 } 157 } 158 159 // This compares A and B for equality. Equals(double A,double B)160 static bool Equals(double A, double B) { 161 return A == B; 162 } 163 164 // This checks if the function "exit" is reachable from an given function 165 // via calls, this is necessary to check if a profile is valid despite the 166 // counts not fitting exactly. 167 template<class FType, class BType> exitReachable(const FType * F)168 bool ProfileVerifierPassT<FType, BType>::exitReachable(const FType *F) { 169 if (!F) return false; 170 171 if (FisVisited.count(F)) return false; 172 173 FType *Exit = F->getParent()->getFunction("exit"); 174 if (Exit == F) { 175 return true; 176 } 177 178 FisVisited.insert(F); 179 bool exits = false; 180 for (const_inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) { 181 if (const CallInst *CI = dyn_cast<CallInst>(&*I)) { 182 FType *F = CI->getCalledFunction(); 183 if (F) { 184 exits |= exitReachable(F); 185 } else { 186 // This is a call to a pointer, all bets are off... 187 exits = true; 188 } 189 if (exits) break; 190 } 191 } 192 return exits; 193 } 194 195 #define ASSERTMESSAGE(M) \ 196 { dbgs() << "ASSERT:" << (M) << "\n"; \ 197 if (!DisableAssertions) assert(0 && (M)); } 198 199 template<class FType, class BType> ReadOrAssert(typename ProfileInfoT<FType,BType>::Edge E)200 double ProfileVerifierPassT<FType, BType>::ReadOrAssert(typename ProfileInfoT<FType, BType>::Edge E) { 201 double EdgeWeight = PI->getEdgeWeight(E); 202 if (EdgeWeight == ProfileInfoT<FType, BType>::MissingValue) { 203 dbgs() << "Edge " << E << " in Function " 204 << ProfileInfoT<FType, BType>::getFunction(E)->getNameStr() << ": "; 205 ASSERTMESSAGE("Edge has missing value"); 206 return 0; 207 } else { 208 if (EdgeWeight < 0) { 209 dbgs() << "Edge " << E << " in Function " 210 << ProfileInfoT<FType, BType>::getFunction(E)->getNameStr() << ": "; 211 ASSERTMESSAGE("Edge has negative value"); 212 } 213 return EdgeWeight; 214 } 215 } 216 217 template<class FType, class BType> CheckValue(bool Error,const char * Message,DetailedBlockInfo * DI)218 void ProfileVerifierPassT<FType, BType>::CheckValue(bool Error, 219 const char *Message, 220 DetailedBlockInfo *DI) { 221 if (Error) { 222 DEBUG(debugEntry(DI)); 223 dbgs() << "Block " << DI->BB->getNameStr() << " in Function " 224 << DI->BB->getParent()->getNameStr() << ": "; 225 ASSERTMESSAGE(Message); 226 } 227 return; 228 } 229 230 // This calculates the Information for a block and then recurses into the 231 // successors. 232 template<class FType, class BType> recurseBasicBlock(const BType * BB)233 void ProfileVerifierPassT<FType, BType>::recurseBasicBlock(const BType *BB) { 234 235 // Break the recursion by remembering all visited blocks. 236 if (BBisVisited.find(BB) != BBisVisited.end()) return; 237 238 // Use a data structure to store all the information, this can then be handed 239 // to debug printers. 240 DetailedBlockInfo DI; 241 DI.BB = BB; 242 DI.outCount = DI.inCount = 0; 243 DI.inWeight = DI.outWeight = 0; 244 245 // Read predecessors. 246 std::set<const BType*> ProcessedPreds; 247 const_pred_iterator bpi = pred_begin(BB), bpe = pred_end(BB); 248 // If there are none, check for (0,BB) edge. 249 if (bpi == bpe) { 250 DI.inWeight += ReadOrAssert(PI->getEdge(0,BB)); 251 DI.inCount++; 252 } 253 for (;bpi != bpe; ++bpi) { 254 if (ProcessedPreds.insert(*bpi).second) { 255 DI.inWeight += ReadOrAssert(PI->getEdge(*bpi,BB)); 256 DI.inCount++; 257 } 258 } 259 260 // Read successors. 261 std::set<const BType*> ProcessedSuccs; 262 succ_const_iterator bbi = succ_begin(BB), bbe = succ_end(BB); 263 // If there is an (0,BB) edge, consider it too. (This is done not only when 264 // there are no successors, but every time; not every function contains 265 // return blocks with no successors (think loop latch as return block)). 266 double w = PI->getEdgeWeight(PI->getEdge(BB,0)); 267 if (w != ProfileInfoT<FType, BType>::MissingValue) { 268 DI.outWeight += w; 269 DI.outCount++; 270 } 271 for (;bbi != bbe; ++bbi) { 272 if (ProcessedSuccs.insert(*bbi).second) { 273 DI.outWeight += ReadOrAssert(PI->getEdge(BB,*bbi)); 274 DI.outCount++; 275 } 276 } 277 278 // Read block weight. 279 DI.BBWeight = PI->getExecutionCount(BB); 280 CheckValue(DI.BBWeight == ProfileInfoT<FType, BType>::MissingValue, 281 "BasicBlock has missing value", &DI); 282 CheckValue(DI.BBWeight < 0, 283 "BasicBlock has negative value", &DI); 284 285 // Check if this block is a setjmp target. 286 bool isSetJmpTarget = false; 287 if (DI.outWeight > DI.inWeight) { 288 for (typename BType::const_iterator i = BB->begin(), ie = BB->end(); 289 i != ie; ++i) { 290 if (const CallInst *CI = dyn_cast<CallInst>(&*i)) { 291 FType *F = CI->getCalledFunction(); 292 if (F && (F->getName() == "_setjmp")) { 293 isSetJmpTarget = true; break; 294 } 295 } 296 } 297 } 298 // Check if this block is eventually reaching exit. 299 bool isExitReachable = false; 300 if (DI.inWeight > DI.outWeight) { 301 for (typename BType::const_iterator i = BB->begin(), ie = BB->end(); 302 i != ie; ++i) { 303 if (const CallInst *CI = dyn_cast<CallInst>(&*i)) { 304 FType *F = CI->getCalledFunction(); 305 if (F) { 306 FisVisited.clear(); 307 isExitReachable |= exitReachable(F); 308 } else { 309 // This is a call to a pointer, all bets are off... 310 isExitReachable = true; 311 } 312 if (isExitReachable) break; 313 } 314 } 315 } 316 317 if (DI.inCount > 0 && DI.outCount == 0) { 318 // If this is a block with no successors. 319 if (!isSetJmpTarget) { 320 CheckValue(!Equals(DI.inWeight,DI.BBWeight), 321 "inWeight and BBWeight do not match", &DI); 322 } 323 } else if (DI.inCount == 0 && DI.outCount > 0) { 324 // If this is a block with no predecessors. 325 if (!isExitReachable) 326 CheckValue(!Equals(DI.BBWeight,DI.outWeight), 327 "BBWeight and outWeight do not match", &DI); 328 } else { 329 // If this block has successors and predecessors. 330 if (DI.inWeight > DI.outWeight && !isExitReachable) 331 CheckValue(!Equals(DI.inWeight,DI.outWeight), 332 "inWeight and outWeight do not match", &DI); 333 if (DI.inWeight < DI.outWeight && !isSetJmpTarget) 334 CheckValue(!Equals(DI.inWeight,DI.outWeight), 335 "inWeight and outWeight do not match", &DI); 336 } 337 338 339 // Mark this block as visited, rescurse into successors. 340 BBisVisited.insert(BB); 341 for ( succ_const_iterator bbi = succ_begin(BB), bbe = succ_end(BB); 342 bbi != bbe; ++bbi ) { 343 recurseBasicBlock(*bbi); 344 } 345 } 346 347 template<class FType, class BType> runOnFunction(FType & F)348 bool ProfileVerifierPassT<FType, BType>::runOnFunction(FType &F) { 349 PI = getAnalysisIfAvailable<ProfileInfoT<FType, BType> >(); 350 if (!PI) 351 ASSERTMESSAGE("No ProfileInfo available"); 352 353 // Prepare global variables. 354 PrintedDebugTree = false; 355 BBisVisited.clear(); 356 357 // Fetch entry block and recurse into it. 358 const BType *entry = &F.getEntryBlock(); 359 recurseBasicBlock(entry); 360 361 if (PI->getExecutionCount(&F) != PI->getExecutionCount(entry)) 362 ASSERTMESSAGE("Function count and entry block count do not match"); 363 364 return false; 365 } 366 367 template<class FType, class BType> 368 char ProfileVerifierPassT<FType, BType>::ID = 0; 369 } 370 371 INITIALIZE_PASS_BEGIN(ProfileVerifierPass, "profile-verifier", 372 "Verify profiling information", false, true) 373 INITIALIZE_AG_DEPENDENCY(ProfileInfo) 374 INITIALIZE_PASS_END(ProfileVerifierPass, "profile-verifier", 375 "Verify profiling information", false, true) 376 377 namespace llvm { createProfileVerifierPass()378 FunctionPass *createProfileVerifierPass() { 379 return new ProfileVerifierPass(ProfileVerifierDisableAssertions); 380 } 381 } 382 383