X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FAnalysis%2FProfileVerifierPass.cpp;h=a01751849c519d16eeeba7064b79e1a2fc052b61;hb=4dbe200b2d3da0dfd1c788c9650b8b8075c241aa;hp=0be4de440fbd76ba539ae5fa60e416a7fc7b7e9e;hpb=0c0de66ea40df4c7ef64d7d5259507b72e8c4d1f;p=oota-llvm.git diff --git a/lib/Analysis/ProfileVerifierPass.cpp b/lib/Analysis/ProfileVerifierPass.cpp index 0be4de440fb..a01751849c5 100644 --- a/lib/Analysis/ProfileVerifierPass.cpp +++ b/lib/Analysis/ProfileVerifierPass.cpp @@ -21,6 +21,7 @@ #include "llvm/Support/CFG.h" #include "llvm/Support/InstIterator.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Support/Format.h" #include "llvm/Support/Debug.h" #include using namespace llvm; @@ -29,44 +30,47 @@ static cl::opt ProfileVerifierDisableAssertions("profile-verifier-noassert", cl::desc("Disable assertions")); -namespace { - class VISIBILITY_HIDDEN ProfileVerifierPass : public FunctionPass { +namespace llvm { + template + class ProfileVerifierPassT : public FunctionPass { struct DetailedBlockInfo { - const BasicBlock *BB; - double BBWeight; - double inWeight; - int inCount; - double outWeight; - int outCount; + const BType *BB; + double BBWeight; + double inWeight; + int inCount; + double outWeight; + int outCount; }; - ProfileInfo *PI; - std::set BBisVisited; - std::set FisVisited; + ProfileInfoT *PI; + std::set BBisVisited; + std::set FisVisited; bool DisableAssertions; // When debugging is enabled, the verifier prints a whole slew of debug // information, otherwise its just the assert. These are all the helper // functions. bool PrintedDebugTree; - std::set BBisPrinted; + std::set BBisPrinted; void debugEntry(DetailedBlockInfo*); - void printDebugInfo(const BasicBlock *BB); + void printDebugInfo(const BType *BB); public: static char ID; // Class identification, replacement for typeinfo - explicit ProfileVerifierPass () : FunctionPass(&ID) { + explicit ProfileVerifierPassT () : FunctionPass(ID) { + initializeProfileVerifierPassPass(*PassRegistry::getPassRegistry()); DisableAssertions = ProfileVerifierDisableAssertions; } - explicit ProfileVerifierPass (bool da) : FunctionPass(&ID), - DisableAssertions(da) { + explicit ProfileVerifierPassT (bool da) : FunctionPass(ID), + DisableAssertions(da) { + initializeProfileVerifierPassPass(*PassRegistry::getPassRegistry()); } void getAnalysisUsage(AnalysisUsage &AU) const { AU.setPreservesAll(); - AU.addRequired(); + AU.addRequired >(); } const char *getPassName() const { @@ -74,259 +78,305 @@ namespace { } /// run - Verify the profile information. - bool runOnFunction(Function &F); - void recurseBasicBlock(const BasicBlock*); + bool runOnFunction(FType &F); + void recurseBasicBlock(const BType*); - bool exitReachable(const Function*); - double ReadOrAssert(ProfileInfo::Edge); + bool exitReachable(const FType*); + double ReadOrAssert(typename ProfileInfoT::Edge); void CheckValue(bool, const char*, DetailedBlockInfo*); }; -} // End of anonymous namespace - -char ProfileVerifierPass::ID = 0; -static RegisterPass -X("profile-verifier", "Verify profiling information", false, true); - -namespace llvm { - FunctionPass *createProfileVerifierPass() { - return new ProfileVerifierPass(ProfileVerifierDisableAssertions); - } -} -void ProfileVerifierPass::printDebugInfo(const BasicBlock *BB) { - - if (BBisPrinted.find(BB) != BBisPrinted.end()) return; - - double BBWeight = PI->getExecutionCount(BB); - if (BBWeight == ProfileInfo::MissingValue) { BBWeight = 0; } - double inWeight = 0; - int inCount = 0; - std::set ProcessedPreds; - for ( pred_const_iterator bbi = pred_begin(BB), bbe = pred_end(BB); - bbi != bbe; ++bbi ) { - if (ProcessedPreds.insert(*bbi).second) { - ProfileInfo::Edge E = PI->getEdge(*bbi,BB); - double EdgeWeight = PI->getEdgeWeight(E); - if (EdgeWeight == ProfileInfo::MissingValue) { EdgeWeight = 0; } - errs() << "calculated in-edge " << E << ": " << EdgeWeight << "\n"; - inWeight += EdgeWeight; - inCount++; + typedef ProfileVerifierPassT ProfileVerifierPass; + + template + void ProfileVerifierPassT::printDebugInfo(const BType *BB) { + + if (BBisPrinted.find(BB) != BBisPrinted.end()) return; + + double BBWeight = PI->getExecutionCount(BB); + if (BBWeight == ProfileInfoT::MissingValue) { BBWeight = 0; } + double inWeight = 0; + int inCount = 0; + std::set ProcessedPreds; + for (const_pred_iterator bbi = pred_begin(BB), bbe = pred_end(BB); + bbi != bbe; ++bbi ) { + if (ProcessedPreds.insert(*bbi).second) { + typename ProfileInfoT::Edge E = PI->getEdge(*bbi,BB); + double EdgeWeight = PI->getEdgeWeight(E); + if (EdgeWeight == ProfileInfoT::MissingValue) { EdgeWeight = 0; } + dbgs() << "calculated in-edge " << E << ": " + << format("%20.20g",EdgeWeight) << "\n"; + inWeight += EdgeWeight; + inCount++; + } } - } - double outWeight = 0; - int outCount = 0; - std::set ProcessedSuccs; - for ( succ_const_iterator bbi = succ_begin(BB), bbe = succ_end(BB); - bbi != bbe; ++bbi ) { - if (ProcessedSuccs.insert(*bbi).second) { - ProfileInfo::Edge E = PI->getEdge(BB,*bbi); - double EdgeWeight = PI->getEdgeWeight(E); - if (EdgeWeight == ProfileInfo::MissingValue) { EdgeWeight = 0; } - errs() << "calculated out-edge " << E << ": " << EdgeWeight << "\n"; - outWeight += EdgeWeight; - outCount++; + double outWeight = 0; + int outCount = 0; + std::set ProcessedSuccs; + for ( succ_const_iterator bbi = succ_begin(BB), bbe = succ_end(BB); + bbi != bbe; ++bbi ) { + if (ProcessedSuccs.insert(*bbi).second) { + typename ProfileInfoT::Edge E = PI->getEdge(BB,*bbi); + double EdgeWeight = PI->getEdgeWeight(E); + if (EdgeWeight == ProfileInfoT::MissingValue) { EdgeWeight = 0; } + dbgs() << "calculated out-edge " << E << ": " + << format("%20.20g",EdgeWeight) << "\n"; + outWeight += EdgeWeight; + outCount++; + } + } + dbgs() << "Block " << BB->getNameStr() << " in " + << BB->getParent()->getNameStr() << ":" + << "BBWeight=" << format("%20.20g",BBWeight) << "," + << "inWeight=" << format("%20.20g",inWeight) << "," + << "inCount=" << inCount << "," + << "outWeight=" << format("%20.20g",outWeight) << "," + << "outCount" << outCount << "\n"; + + // mark as visited and recurse into subnodes + BBisPrinted.insert(BB); + for ( succ_const_iterator bbi = succ_begin(BB), bbe = succ_end(BB); + bbi != bbe; ++bbi ) { + printDebugInfo(*bbi); } } - errs()<<"Block "<getNameStr()<<" in "<getParent()->getNameStr() - <<",BBWeight="<BB->getNameStr() << " in " - << DI->BB->getParent()->getNameStr() << ":"; - errs() << "BBWeight=" << DI->BBWeight << ","; - errs() << "inWeight=" << DI->inWeight << ","; - errs() << "inCount=" << DI->inCount << ","; - errs() << "outWeight=" << DI->outWeight << ","; - errs() << "outCount=" << DI->outCount << "\n"; - if (!PrintedDebugTree) { - PrintedDebugTree = true; - printDebugInfo(&(DI->BB->getParent()->getEntryBlock())); + template + void ProfileVerifierPassT::debugEntry (DetailedBlockInfo *DI) { + dbgs() << "TROUBLE: Block " << DI->BB->getNameStr() << " in " + << DI->BB->getParent()->getNameStr() << ":" + << "BBWeight=" << format("%20.20g",DI->BBWeight) << "," + << "inWeight=" << format("%20.20g",DI->inWeight) << "," + << "inCount=" << DI->inCount << "," + << "outWeight=" << format("%20.20g",DI->outWeight) << "," + << "outCount=" << DI->outCount << "\n"; + if (!PrintedDebugTree) { + PrintedDebugTree = true; + printDebugInfo(&(DI->BB->getParent()->getEntryBlock())); + } } -} -// compare with relative error -static bool Equals(double A, double B) { - double maxRelativeError = 0.0000001; - if (A == B) - return true; - double relativeError; - if (fabs(B) > fabs(A)) - relativeError = fabs((A - B) / B); - else - relativeError = fabs((A - B) / A); - if (relativeError <= maxRelativeError) return true; - return false; -} + // This compares A and B for equality. + static bool Equals(double A, double B) { + return A == B; + } -bool ProfileVerifierPass::exitReachable(const Function *F) { - if (!F) return false; + // This checks if the function "exit" is reachable from an given function + // via calls, this is necessary to check if a profile is valid despite the + // counts not fitting exactly. + template + bool ProfileVerifierPassT::exitReachable(const FType *F) { + if (!F) return false; - if (FisVisited.count(F)) return false; + if (FisVisited.count(F)) return false; - Function *Exit = F->getParent()->getFunction("exit"); - if (Exit == F) { - return true; - } + FType *Exit = F->getParent()->getFunction("exit"); + if (Exit == F) { + return true; + } - FisVisited.insert(F); - bool exits = false; - for (const_inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) { - if (const CallInst *CI = dyn_cast(&*I)) { - exits |= exitReachable(CI->getCalledFunction()); - if (exits) break; + FisVisited.insert(F); + bool exits = false; + for (const_inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) { + if (const CallInst *CI = dyn_cast(&*I)) { + FType *F = CI->getCalledFunction(); + if (F) { + exits |= exitReachable(F); + } else { + // This is a call to a pointer, all bets are off... + exits = true; + } + if (exits) break; + } } + return exits; } - return exits; -} -#define ASSERTMESSAGE(M) \ - errs() << (M) << "\n"; \ - if (!DisableAssertions) assert(0 && (M)); - -double ProfileVerifierPass::ReadOrAssert(ProfileInfo::Edge E) { - double EdgeWeight = PI->getEdgeWeight(E); - if (EdgeWeight == ProfileInfo::MissingValue) { - errs() << "Edge " << E << " in Function " - << E.first->getParent()->getNameStr() << ": "; - ASSERTMESSAGE("ASSERT:Edge has missing value"); - return 0; - } else { - return EdgeWeight; + #define ASSERTMESSAGE(M) \ + { dbgs() << "ASSERT:" << (M) << "\n"; \ + if (!DisableAssertions) assert(0 && (M)); } + + template + double ProfileVerifierPassT::ReadOrAssert(typename ProfileInfoT::Edge E) { + double EdgeWeight = PI->getEdgeWeight(E); + if (EdgeWeight == ProfileInfoT::MissingValue) { + dbgs() << "Edge " << E << " in Function " + << ProfileInfoT::getFunction(E)->getNameStr() << ": "; + ASSERTMESSAGE("Edge has missing value"); + return 0; + } else { + if (EdgeWeight < 0) { + dbgs() << "Edge " << E << " in Function " + << ProfileInfoT::getFunction(E)->getNameStr() << ": "; + ASSERTMESSAGE("Edge has negative value"); + } + return EdgeWeight; + } } -} -void ProfileVerifierPass::CheckValue(bool Error, const char *Message, - DetailedBlockInfo *DI) { - if (Error) { - DEBUG(debugEntry(DI)); - errs() << "Block " << DI->BB->getNameStr() << " in Function " - << DI->BB->getParent()->getNameStr() << ": "; - ASSERTMESSAGE(Message); + template + void ProfileVerifierPassT::CheckValue(bool Error, + const char *Message, + DetailedBlockInfo *DI) { + if (Error) { + DEBUG(debugEntry(DI)); + dbgs() << "Block " << DI->BB->getNameStr() << " in Function " + << DI->BB->getParent()->getNameStr() << ": "; + ASSERTMESSAGE(Message); + } + return; } - return; -} - -void ProfileVerifierPass::recurseBasicBlock(const BasicBlock *BB) { - if (BBisVisited.find(BB) != BBisVisited.end()) return; - - DetailedBlockInfo DI; - DI.BB = BB; - DI.outCount = DI.inCount = DI.inWeight = DI.outWeight = 0; - std::set ProcessedPreds; - pred_const_iterator bpi = pred_begin(BB), bpe = pred_end(BB); - if (bpi == bpe) { - DI.inWeight += ReadOrAssert(PI->getEdge(0,BB)); - DI.inCount++; - } - for (;bpi != bpe; ++bpi) { - if (ProcessedPreds.insert(*bpi).second) { - DI.inWeight += ReadOrAssert(PI->getEdge(*bpi,BB)); + // This calculates the Information for a block and then recurses into the + // successors. + template + void ProfileVerifierPassT::recurseBasicBlock(const BType *BB) { + + // Break the recursion by remembering all visited blocks. + if (BBisVisited.find(BB) != BBisVisited.end()) return; + + // Use a data structure to store all the information, this can then be handed + // to debug printers. + DetailedBlockInfo DI; + DI.BB = BB; + DI.outCount = DI.inCount = 0; + DI.inWeight = DI.outWeight = 0; + + // Read predecessors. + std::set ProcessedPreds; + const_pred_iterator bpi = pred_begin(BB), bpe = pred_end(BB); + // If there are none, check for (0,BB) edge. + if (bpi == bpe) { + DI.inWeight += ReadOrAssert(PI->getEdge(0,BB)); DI.inCount++; } - } + for (;bpi != bpe; ++bpi) { + if (ProcessedPreds.insert(*bpi).second) { + DI.inWeight += ReadOrAssert(PI->getEdge(*bpi,BB)); + DI.inCount++; + } + } - std::set ProcessedSuccs; - succ_const_iterator bbi = succ_begin(BB), bbe = succ_end(BB); - if (bbi == bbe) { + // Read successors. + std::set ProcessedSuccs; + succ_const_iterator bbi = succ_begin(BB), bbe = succ_end(BB); + // If there is an (0,BB) edge, consider it too. (This is done not only when + // there are no successors, but every time; not every function contains + // return blocks with no successors (think loop latch as return block)). double w = PI->getEdgeWeight(PI->getEdge(BB,0)); - if (w != ProfileInfo::MissingValue) { + if (w != ProfileInfoT::MissingValue) { DI.outWeight += w; DI.outCount++; } - } - for (;bbi != bbe; ++bbi) { - if (ProcessedSuccs.insert(*bbi).second) { - DI.outWeight += ReadOrAssert(PI->getEdge(BB,*bbi)); - DI.outCount++; + for (;bbi != bbe; ++bbi) { + if (ProcessedSuccs.insert(*bbi).second) { + DI.outWeight += ReadOrAssert(PI->getEdge(BB,*bbi)); + DI.outCount++; + } } - } - DI.BBWeight = PI->getExecutionCount(BB); - CheckValue(DI.BBWeight == ProfileInfo::MissingValue, - "ASSERT:BasicBlock has missing value", &DI); - - // Check if this block is a setjmp target. - bool isSetJmpTarget = false; - if (DI.outWeight > DI.inWeight) { - for (BasicBlock::const_iterator i = BB->begin(), ie = BB->end(); - i != ie; ++i) { - if (const CallInst *CI = dyn_cast(&*i)) { - Function *F = CI->getCalledFunction(); - if (F && (F->getNameStr() == "_setjmp")) { - isSetJmpTarget = true; break; + // Read block weight. + DI.BBWeight = PI->getExecutionCount(BB); + CheckValue(DI.BBWeight == ProfileInfoT::MissingValue, + "BasicBlock has missing value", &DI); + CheckValue(DI.BBWeight < 0, + "BasicBlock has negative value", &DI); + + // Check if this block is a setjmp target. + bool isSetJmpTarget = false; + if (DI.outWeight > DI.inWeight) { + for (typename BType::const_iterator i = BB->begin(), ie = BB->end(); + i != ie; ++i) { + if (const CallInst *CI = dyn_cast(&*i)) { + FType *F = CI->getCalledFunction(); + if (F && (F->getName() == "_setjmp")) { + isSetJmpTarget = true; break; + } } } } - } - // Check if this block is eventually reaching exit. - bool isExitReachable = false; - if (DI.inWeight > DI.outWeight) { - for (BasicBlock::const_iterator i = BB->begin(), ie = BB->end(); - i != ie; ++i) { - if (const CallInst *CI = dyn_cast(&*i)) { - FisVisited.clear(); - isExitReachable |= exitReachable(CI->getCalledFunction()); - if (isExitReachable) break; + // Check if this block is eventually reaching exit. + bool isExitReachable = false; + if (DI.inWeight > DI.outWeight) { + for (typename BType::const_iterator i = BB->begin(), ie = BB->end(); + i != ie; ++i) { + if (const CallInst *CI = dyn_cast(&*i)) { + FType *F = CI->getCalledFunction(); + if (F) { + FisVisited.clear(); + isExitReachable |= exitReachable(F); + } else { + // This is a call to a pointer, all bets are off... + isExitReachable = true; + } + if (isExitReachable) break; + } } } - } - if (DI.inCount > 0 && DI.outCount == 0) { - // If this is a block with no successors. - if (!isSetJmpTarget) { - CheckValue(!Equals(DI.inWeight,DI.BBWeight), - "ASSERT:inWeight and BBWeight do not match", &DI); + if (DI.inCount > 0 && DI.outCount == 0) { + // If this is a block with no successors. + if (!isSetJmpTarget) { + CheckValue(!Equals(DI.inWeight,DI.BBWeight), + "inWeight and BBWeight do not match", &DI); + } + } else if (DI.inCount == 0 && DI.outCount > 0) { + // If this is a block with no predecessors. + if (!isExitReachable) + CheckValue(!Equals(DI.BBWeight,DI.outWeight), + "BBWeight and outWeight do not match", &DI); + } else { + // If this block has successors and predecessors. + if (DI.inWeight > DI.outWeight && !isExitReachable) + CheckValue(!Equals(DI.inWeight,DI.outWeight), + "inWeight and outWeight do not match", &DI); + if (DI.inWeight < DI.outWeight && !isSetJmpTarget) + CheckValue(!Equals(DI.inWeight,DI.outWeight), + "inWeight and outWeight do not match", &DI); } - } else if (DI.inCount == 0 && DI.outCount > 0) { - // If this is a block with no predecessors. - if (!isExitReachable) - CheckValue(!Equals(DI.BBWeight,DI.outWeight), - "ASSERT:BBWeight and outWeight do not match", &DI); - } else { - // If this block has successors and predecessors. - if (DI.inWeight > DI.outWeight && !isExitReachable) - CheckValue(!Equals(DI.inWeight,DI.outWeight), - "ASSERT:inWeight and outWeight do not match", &DI); - if (DI.inWeight < DI.outWeight && !isSetJmpTarget) - CheckValue(!Equals(DI.inWeight,DI.outWeight), - "ASSERT:inWeight and outWeight do not match", &DI); - } - // mark as visited and recurse into subnodes - BBisVisited.insert(BB); - for ( succ_const_iterator bbi = succ_begin(BB), bbe = succ_end(BB); - bbi != bbe; ++bbi ) { - recurseBasicBlock(*bbi); + // Mark this block as visited, rescurse into successors. + BBisVisited.insert(BB); + for ( succ_const_iterator bbi = succ_begin(BB), bbe = succ_end(BB); + bbi != bbe; ++bbi ) { + recurseBasicBlock(*bbi); + } } -} -bool ProfileVerifierPass::runOnFunction(Function &F) { - PI = &getAnalysis(); + template + bool ProfileVerifierPassT::runOnFunction(FType &F) { + PI = getAnalysisIfAvailable >(); + if (!PI) + ASSERTMESSAGE("No ProfileInfo available"); + + // Prepare global variables. + PrintedDebugTree = false; + BBisVisited.clear(); + + // Fetch entry block and recurse into it. + const BType *entry = &F.getEntryBlock(); + recurseBasicBlock(entry); + + if (PI->getExecutionCount(&F) != PI->getExecutionCount(entry)) + ASSERTMESSAGE("Function count and entry block count do not match"); - if (PI->getExecutionCount(&F) == ProfileInfo::MissingValue) { - DEBUG(errs() << "Function " << F.getNameStr() << " has no profile\n"); return false; } - PrintedDebugTree = false; - BBisVisited.clear(); + template + char ProfileVerifierPassT::ID = 0; +} - const BasicBlock *entry = &F.getEntryBlock(); - recurseBasicBlock(entry); +INITIALIZE_PASS_BEGIN(ProfileVerifierPass, "profile-verifier", + "Verify profiling information", false, true) +INITIALIZE_AG_DEPENDENCY(ProfileInfo) +INITIALIZE_PASS_END(ProfileVerifierPass, "profile-verifier", + "Verify profiling information", false, true) - if (!DisableAssertions) - assert((PI->getExecutionCount(&F)==PI->getExecutionCount(entry)) && - "Function count and entry block count do not match"); - return false; +namespace llvm { + FunctionPass *createProfileVerifierPass() { + return new ProfileVerifierPass(ProfileVerifierDisableAssertions); + } } +