Cleaned up ProfileVerifierPass.

(See http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20090831/086219.html)


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@81007 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Andreas Neustifter 2009-09-04 17:15:10 +00:00
parent ed1ac4ae8e
commit e8d372e48d

View File

@ -21,27 +21,39 @@
#include <set> #include <set>
using namespace llvm; using namespace llvm;
static bool DisableAssertions = false;
static cl::opt<bool,true> static cl::opt<bool,true>
ProfileVerifierDisableAssertions("profile-verifier-noassert", ProfileVerifierDisableAssertions("profile-verifier-noassert",
cl::location(DisableAssertions), cl::desc("Disable assertions")); cl::desc("Disable assertions"));
bool PrintedDebugTree = false;
namespace { namespace {
class VISIBILITY_HIDDEN ProfileVerifierPass : public FunctionPass { class VISIBILITY_HIDDEN ProfileVerifierPass : public FunctionPass {
struct DetailedBlockInfo {
const BasicBlock *BB;
double BBWeight;
double inWeight;
int inCount;
double outWeight;
int outCount;
};
ProfileInfo *PI; ProfileInfo *PI;
std::set<const BasicBlock*> BBisVisited; std::set<const BasicBlock*> BBisVisited;
#ifndef NDEBUG 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<const BasicBlock*> BBisPrinted; std::set<const BasicBlock*> BBisPrinted;
void debugEntry(const BasicBlock* BB, double w, double inw, int inc, void debugEntry(DetailedBlockInfo*);
double outw, int outc, double d);
void printDebugInfo(const BasicBlock *BB); void printDebugInfo(const BasicBlock *BB);
#endif
public: public:
static char ID; // Class identification, replacement for typeinfo static char ID; // Class identification, replacement for typeinfo
explicit ProfileVerifierPass () : FunctionPass(&ID) { explicit ProfileVerifierPass (bool da = false) : FunctionPass(&ID),
DisableAssertions = ProfileVerifierDisableAssertions; DisableAssertions(da) {
} }
void getAnalysisUsage(AnalysisUsage &AU) const { void getAnalysisUsage(AnalysisUsage &AU) const {
@ -56,6 +68,9 @@ namespace {
/// run - Verify the profile information. /// run - Verify the profile information.
bool runOnFunction(Function &F); bool runOnFunction(Function &F);
void recurseBasicBlock(const BasicBlock *BB); void recurseBasicBlock(const BasicBlock *BB);
double ReadOrAssert(ProfileInfo::Edge);
void CheckValue(bool, const char*, DetailedBlockInfo*);
}; };
} // End of anonymous namespace } // End of anonymous namespace
@ -65,11 +80,10 @@ X("profile-verifier", "Verify profiling information", false, true);
namespace llvm { namespace llvm {
FunctionPass *createProfileVerifierPass() { FunctionPass *createProfileVerifierPass() {
return new ProfileVerifierPass(); return new ProfileVerifierPass(ProfileVerifierDisableAssertions);
} }
} }
#ifndef NDEBUG
void ProfileVerifierPass::printDebugInfo(const BasicBlock *BB) { void ProfileVerifierPass::printDebugInfo(const BasicBlock *BB) {
if (BBisPrinted.find(BB) != BBisPrinted.end()) return; if (BBisPrinted.find(BB) != BBisPrinted.end()) return;
@ -84,8 +98,8 @@ void ProfileVerifierPass::printDebugInfo(const BasicBlock *BB) {
if (ProcessedPreds.insert(*bbi).second) { if (ProcessedPreds.insert(*bbi).second) {
double EdgeWeight = PI->getEdgeWeight(PI->getEdge(*bbi,BB)); double EdgeWeight = PI->getEdgeWeight(PI->getEdge(*bbi,BB));
if (EdgeWeight == ProfileInfo::MissingValue) { EdgeWeight = 0; } if (EdgeWeight == ProfileInfo::MissingValue) { EdgeWeight = 0; }
DEBUG(errs()<<"calculated in-edge ("<<(*bbi)->getNameStr()<<","<<BB->getNameStr() errs()<<"calculated in-edge ("<<(*bbi)->getNameStr()<<","<<BB->getNameStr()
<<"): "<<EdgeWeight<<"\n"); <<"): "<<EdgeWeight<<"\n";
inWeight += EdgeWeight; inWeight += EdgeWeight;
inCount++; inCount++;
} }
@ -98,15 +112,15 @@ void ProfileVerifierPass::printDebugInfo(const BasicBlock *BB) {
if (ProcessedSuccs.insert(*bbi).second) { if (ProcessedSuccs.insert(*bbi).second) {
double EdgeWeight = PI->getEdgeWeight(PI->getEdge(BB,*bbi)); double EdgeWeight = PI->getEdgeWeight(PI->getEdge(BB,*bbi));
if (EdgeWeight == ProfileInfo::MissingValue) { EdgeWeight = 0; } if (EdgeWeight == ProfileInfo::MissingValue) { EdgeWeight = 0; }
DEBUG(errs()<<"calculated out-edge ("<<BB->getNameStr()<<","<<(*bbi)->getNameStr() errs()<<"calculated out-edge ("<<BB->getNameStr()<<","<<(*bbi)->getNameStr()
<<"): "<<EdgeWeight<<"\n"); <<"): "<<EdgeWeight<<"\n";
outWeight += EdgeWeight; outWeight += EdgeWeight;
outCount++; outCount++;
} }
} }
DEBUG(errs()<<"Block "<<BB->getNameStr()<<" in "<<BB->getParent()->getNameStr() errs()<<"Block "<<BB->getNameStr()<<" in "<<BB->getParent()->getNameStr()
<<",BBWeight="<<BBWeight<<",inWeight="<<inWeight<<",inCount="<<inCount <<",BBWeight="<<BBWeight<<",inWeight="<<inWeight<<",inCount="<<inCount
<<",outWeight="<<outWeight<<",outCount"<<outCount<<"\n"); <<",outWeight="<<outWeight<<",outCount"<<outCount<<"\n";
// mark as visited and recurse into subnodes // mark as visited and recurse into subnodes
BBisPrinted.insert(BB); BBisPrinted.insert(BB);
@ -116,22 +130,22 @@ void ProfileVerifierPass::printDebugInfo(const BasicBlock *BB) {
} }
} }
void ProfileVerifierPass::debugEntry (const BasicBlock* BB, double w, void ProfileVerifierPass::debugEntry (DetailedBlockInfo *DI) {
double inw, int inc, double outw, int errs() << "TROUBLE: Block " << DI->BB->getNameStr() << " in "
outc, double d) { << DI->BB->getParent()->getNameStr() << ":";
DEBUG(errs()<<"TROUBLE: Block "<<BB->getNameStr()<<" in "<<BB->getParent()->getNameStr() errs() << "BBWeight=" << DI->BBWeight << ",";
<<",BBWeight="<<w<<",inWeight="<<inw<<",inCount="<<inc<<",outWeight=" errs() << "inWeight=" << DI->inWeight << ",";
<<outw<<",outCount"<<outc<<"\n"); errs() << "inCount=" << DI->inCount << ",";
DEBUG(errs()<<"DELTA:"<<d<<"\n"); errs() << "outWeight=" << DI->outWeight << ",";
errs() << "outCount=" << DI->outCount << ",";
if (!PrintedDebugTree) { if (!PrintedDebugTree) {
PrintedDebugTree = true; PrintedDebugTree = true;
printDebugInfo(&(BB->getParent()->getEntryBlock())); printDebugInfo(&(DI->BB->getParent()->getEntryBlock()));
} }
} }
#endif
// compare with relative error // compare with relative error
static bool dcmp(double A, double B) { static bool Equals(double A, double B) {
double maxRelativeError = 0.0000001; double maxRelativeError = 0.0000001;
if (A == B) if (A == B)
return true; return true;
@ -144,59 +158,66 @@ static bool dcmp(double A, double B) {
return false; return false;
} }
#define CHECK(C,M) \ double ProfileVerifierPass::ReadOrAssert(ProfileInfo::Edge E) {
if (C) { \ const char *Message = "ASSERT:Edge has missing value";
if (DisableAssertions) { errs()<<(M)<<"\n"; } else { assert((!(C)) && (M)); } \ double EdgeWeight = PI->getEdgeWeight(E);
if (EdgeWeight == ProfileInfo::MissingValue) {
if (DisableAssertions) {
errs() << Message << "\n";
return 0;
} else {
assert(0 && Message);
}
} else {
return EdgeWeight;
}
} }
#define CHECKDEBUG(C,M,D) \ void ProfileVerifierPass::CheckValue(bool Error, const char *Message, DetailedBlockInfo *DI) {
if (C) { \ if (Error) {
DEBUG(debugEntry(BB, BBWeight, inWeight, inCount, \ DEBUG(debugEntry(DI));
outWeight, outCount, (D))); \ if (DisableAssertions) {
if (DisableAssertions) { errs()<<(M)<<"\n"; } else { assert((!(C)) && (M)); } \ errs() << Message << "\n";
} else {
assert(0 && Message);
}
}
return;
} }
void ProfileVerifierPass::recurseBasicBlock(const BasicBlock *BB) { void ProfileVerifierPass::recurseBasicBlock(const BasicBlock *BB) {
if (BBisVisited.find(BB) != BBisVisited.end()) return; if (BBisVisited.find(BB) != BBisVisited.end()) return;
double inWeight = 0; DetailedBlockInfo DI;
int inCount = 0; DI.BB = BB;
DI.outCount = DI.inCount = DI.inWeight = DI.outWeight = 0;
std::set<const BasicBlock*> ProcessedPreds; std::set<const BasicBlock*> ProcessedPreds;
for ( pred_const_iterator bbi = pred_begin(BB), bbe = pred_end(BB); for ( pred_const_iterator bbi = pred_begin(BB), bbe = pred_end(BB);
bbi != bbe; ++bbi ) { bbi != bbe; ++bbi ) {
if (ProcessedPreds.insert(*bbi).second) { if (ProcessedPreds.insert(*bbi).second) {
double EdgeWeight = PI->getEdgeWeight(PI->getEdge(*bbi,BB)); DI.inWeight += ReadOrAssert(PI->getEdge(*bbi,BB));
CHECK(EdgeWeight == ProfileInfo::MissingValue, DI.inCount++;
"ASSERT:Edge has missing value");
inWeight += EdgeWeight; inCount++;
} }
} }
double outWeight = 0;
int outCount = 0;
std::set<const BasicBlock*> ProcessedSuccs; std::set<const BasicBlock*> ProcessedSuccs;
for ( succ_const_iterator bbi = succ_begin(BB), bbe = succ_end(BB); for ( succ_const_iterator bbi = succ_begin(BB), bbe = succ_end(BB);
bbi != bbe; ++bbi ) { bbi != bbe; ++bbi ) {
if (ProcessedSuccs.insert(*bbi).second) { if (ProcessedSuccs.insert(*bbi).second) {
double EdgeWeight = PI->getEdgeWeight(PI->getEdge(BB,*bbi)); DI.outWeight += ReadOrAssert(PI->getEdge(BB,*bbi));
CHECK(EdgeWeight == ProfileInfo::MissingValue, DI.outCount++;
"ASSERT:Edge has missing value");
outWeight += EdgeWeight; outCount++;
} }
} }
double BBWeight = PI->getExecutionCount(BB); DI.BBWeight = PI->getExecutionCount(BB);
CHECKDEBUG(BBWeight == ProfileInfo::MissingValue, CheckValue(DI.BBWeight == ProfileInfo::MissingValue, "ASSERT:BasicBlock has missing value", &DI);
"ASSERT:BasicBlock has missing value",-1);
if (inCount > 0) { if (DI.inCount > 0) {
CHECKDEBUG(!dcmp(inWeight,BBWeight), CheckValue(!Equals(DI.inWeight,DI.BBWeight), "ASSERT:inWeight and BBWeight do not match", &DI);
"ASSERT:inWeight and BBWeight do not match",inWeight-BBWeight);
} }
if (outCount > 0) { if (DI.outCount > 0) {
CHECKDEBUG(!dcmp(outWeight,BBWeight), CheckValue(!Equals(DI.outWeight,DI.BBWeight), "ASSERT:outWeight and BBWeight do not match", &DI);
"ASSERT:outWeight and BBWeight do not match",outWeight-BBWeight);
} }
// mark as visited and recurse into subnodes // mark as visited and recurse into subnodes