mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-02-15 09:33:39 +00:00
Fixed wrong storage option for ProfileVerifierDisableAssertions.
Fixed non working -profile-verifier-noassert option. Fixed missing newline in debugEntry(). Cleaned up assert messages. (assert(0 && Message) is still shown, but the message is printed before.) When verifiying loaded profiles the ProfileVerifier got confused when block was a setjmp target, this is checked now. When verifiying loaded profiles the ProfileVerifier got confused when block eventually reaching an exit(), this is checked now. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@81338 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
1f3b00272a
commit
43b1b0e4ff
@ -12,16 +12,20 @@
|
|||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
#define DEBUG_TYPE "profile-verifier"
|
#define DEBUG_TYPE "profile-verifier"
|
||||||
|
#include "llvm/Instructions.h"
|
||||||
|
#include "llvm/Module.h"
|
||||||
#include "llvm/Pass.h"
|
#include "llvm/Pass.h"
|
||||||
#include "llvm/Analysis/ProfileInfo.h"
|
#include "llvm/Analysis/ProfileInfo.h"
|
||||||
#include "llvm/Support/CommandLine.h"
|
#include "llvm/Support/CommandLine.h"
|
||||||
|
#include "llvm/Support/CallSite.h"
|
||||||
#include "llvm/Support/CFG.h"
|
#include "llvm/Support/CFG.h"
|
||||||
|
#include "llvm/Support/InstIterator.h"
|
||||||
#include "llvm/Support/raw_ostream.h"
|
#include "llvm/Support/raw_ostream.h"
|
||||||
#include "llvm/Support/Debug.h"
|
#include "llvm/Support/Debug.h"
|
||||||
#include <set>
|
#include <set>
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
static cl::opt<bool,true>
|
static cl::opt<bool,false>
|
||||||
ProfileVerifierDisableAssertions("profile-verifier-noassert",
|
ProfileVerifierDisableAssertions("profile-verifier-noassert",
|
||||||
cl::desc("Disable assertions"));
|
cl::desc("Disable assertions"));
|
||||||
|
|
||||||
@ -39,6 +43,7 @@ namespace {
|
|||||||
|
|
||||||
ProfileInfo *PI;
|
ProfileInfo *PI;
|
||||||
std::set<const BasicBlock*> BBisVisited;
|
std::set<const BasicBlock*> BBisVisited;
|
||||||
|
std::set<const Function*> FisVisited;
|
||||||
bool DisableAssertions;
|
bool DisableAssertions;
|
||||||
|
|
||||||
// When debugging is enabled, the verifier prints a whole slew of debug
|
// When debugging is enabled, the verifier prints a whole slew of debug
|
||||||
@ -52,8 +57,11 @@ namespace {
|
|||||||
public:
|
public:
|
||||||
static char ID; // Class identification, replacement for typeinfo
|
static char ID; // Class identification, replacement for typeinfo
|
||||||
|
|
||||||
explicit ProfileVerifierPass (bool da = false) : FunctionPass(&ID),
|
explicit ProfileVerifierPass () : FunctionPass(&ID) {
|
||||||
DisableAssertions(da) {
|
DisableAssertions = ProfileVerifierDisableAssertions;
|
||||||
|
}
|
||||||
|
explicit ProfileVerifierPass (bool da) : FunctionPass(&ID),
|
||||||
|
DisableAssertions(da) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void getAnalysisUsage(AnalysisUsage &AU) const {
|
void getAnalysisUsage(AnalysisUsage &AU) const {
|
||||||
@ -67,8 +75,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*);
|
||||||
|
|
||||||
|
bool exitReachable(const Function*);
|
||||||
double ReadOrAssert(ProfileInfo::Edge);
|
double ReadOrAssert(ProfileInfo::Edge);
|
||||||
void CheckValue(bool, const char*, DetailedBlockInfo*);
|
void CheckValue(bool, const char*, DetailedBlockInfo*);
|
||||||
};
|
};
|
||||||
@ -96,10 +105,10 @@ void ProfileVerifierPass::printDebugInfo(const BasicBlock *BB) {
|
|||||||
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));
|
ProfileInfo::Edge E = PI->getEdge(*bbi,BB);
|
||||||
|
double EdgeWeight = PI->getEdgeWeight(E);
|
||||||
if (EdgeWeight == ProfileInfo::MissingValue) { EdgeWeight = 0; }
|
if (EdgeWeight == ProfileInfo::MissingValue) { EdgeWeight = 0; }
|
||||||
errs()<<"calculated in-edge ("<<(*bbi)->getNameStr()<<","<<BB->getNameStr()
|
errs() << "calculated in-edge " << E << ": " << EdgeWeight << "\n";
|
||||||
<<"): "<<EdgeWeight<<"\n";
|
|
||||||
inWeight += EdgeWeight;
|
inWeight += EdgeWeight;
|
||||||
inCount++;
|
inCount++;
|
||||||
}
|
}
|
||||||
@ -110,10 +119,10 @@ void ProfileVerifierPass::printDebugInfo(const BasicBlock *BB) {
|
|||||||
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));
|
ProfileInfo::Edge E = PI->getEdge(BB,*bbi);
|
||||||
|
double EdgeWeight = PI->getEdgeWeight(E);
|
||||||
if (EdgeWeight == ProfileInfo::MissingValue) { EdgeWeight = 0; }
|
if (EdgeWeight == ProfileInfo::MissingValue) { EdgeWeight = 0; }
|
||||||
errs()<<"calculated out-edge ("<<BB->getNameStr()<<","<<(*bbi)->getNameStr()
|
errs() << "calculated out-edge " << E << ": " << EdgeWeight << "\n";
|
||||||
<<"): "<<EdgeWeight<<"\n";
|
|
||||||
outWeight += EdgeWeight;
|
outWeight += EdgeWeight;
|
||||||
outCount++;
|
outCount++;
|
||||||
}
|
}
|
||||||
@ -137,7 +146,7 @@ void ProfileVerifierPass::debugEntry (DetailedBlockInfo *DI) {
|
|||||||
errs() << "inWeight=" << DI->inWeight << ",";
|
errs() << "inWeight=" << DI->inWeight << ",";
|
||||||
errs() << "inCount=" << DI->inCount << ",";
|
errs() << "inCount=" << DI->inCount << ",";
|
||||||
errs() << "outWeight=" << DI->outWeight << ",";
|
errs() << "outWeight=" << DI->outWeight << ",";
|
||||||
errs() << "outCount=" << DI->outCount << ",";
|
errs() << "outCount=" << DI->outCount << "\n";
|
||||||
if (!PrintedDebugTree) {
|
if (!PrintedDebugTree) {
|
||||||
PrintedDebugTree = true;
|
PrintedDebugTree = true;
|
||||||
printDebugInfo(&(DI->BB->getParent()->getEntryBlock()));
|
printDebugInfo(&(DI->BB->getParent()->getEntryBlock()));
|
||||||
@ -158,30 +167,50 @@ static bool Equals(double A, double B) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ProfileVerifierPass::exitReachable(const Function *F) {
|
||||||
|
if (!F) return false;
|
||||||
|
|
||||||
|
if (FisVisited.count(F)) return false;
|
||||||
|
|
||||||
|
Function *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<CallInst>(&*I)) {
|
||||||
|
exits |= exitReachable(CI->getCalledFunction());
|
||||||
|
if (exits) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return exits;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ASSERTMESSAGE(M) \
|
||||||
|
errs() << (M) << "\n"; \
|
||||||
|
if (!DisableAssertions) assert(0 && (M));
|
||||||
|
|
||||||
double ProfileVerifierPass::ReadOrAssert(ProfileInfo::Edge E) {
|
double ProfileVerifierPass::ReadOrAssert(ProfileInfo::Edge E) {
|
||||||
const char *Message = "ASSERT:Edge has missing value";
|
|
||||||
double EdgeWeight = PI->getEdgeWeight(E);
|
double EdgeWeight = PI->getEdgeWeight(E);
|
||||||
if (EdgeWeight == ProfileInfo::MissingValue) {
|
if (EdgeWeight == ProfileInfo::MissingValue) {
|
||||||
if (DisableAssertions) {
|
errs() << "Edge " << E << " in Function "
|
||||||
errs() << Message << "\n";
|
<< E.first->getParent()->getNameStr() << ": ";
|
||||||
return 0;
|
ASSERTMESSAGE("ASSERT:Edge has missing value");
|
||||||
} else {
|
return 0;
|
||||||
assert(0 && Message);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
return EdgeWeight;
|
return EdgeWeight;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProfileVerifierPass::CheckValue(bool Error, const char *Message, DetailedBlockInfo *DI) {
|
void ProfileVerifierPass::CheckValue(bool Error, const char *Message,
|
||||||
|
DetailedBlockInfo *DI) {
|
||||||
if (Error) {
|
if (Error) {
|
||||||
DEBUG(debugEntry(DI));
|
DEBUG(debugEntry(DI));
|
||||||
if (DisableAssertions) {
|
errs() << "Block " << DI->BB->getNameStr() << " in Function "
|
||||||
errs() << Message << "\n";
|
<< DI->BB->getParent()->getNameStr() << ": ";
|
||||||
} else {
|
ASSERTMESSAGE(Message);
|
||||||
assert(0 && Message);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -194,8 +223,8 @@ void ProfileVerifierPass::recurseBasicBlock(const BasicBlock *BB) {
|
|||||||
DI.BB = BB;
|
DI.BB = BB;
|
||||||
DI.outCount = DI.inCount = DI.inWeight = DI.outWeight = 0;
|
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) {
|
||||||
DI.inWeight += ReadOrAssert(PI->getEdge(*bbi,BB));
|
DI.inWeight += ReadOrAssert(PI->getEdge(*bbi,BB));
|
||||||
DI.inCount++;
|
DI.inCount++;
|
||||||
@ -203,8 +232,8 @@ void ProfileVerifierPass::recurseBasicBlock(const BasicBlock *BB) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
||||||
DI.outWeight += ReadOrAssert(PI->getEdge(BB,*bbi));
|
DI.outWeight += ReadOrAssert(PI->getEdge(BB,*bbi));
|
||||||
DI.outCount++;
|
DI.outCount++;
|
||||||
@ -212,15 +241,57 @@ void ProfileVerifierPass::recurseBasicBlock(const BasicBlock *BB) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
DI.BBWeight = PI->getExecutionCount(BB);
|
DI.BBWeight = PI->getExecutionCount(BB);
|
||||||
CheckValue(DI.BBWeight == ProfileInfo::MissingValue, "ASSERT:BasicBlock has missing value", &DI);
|
CheckValue(DI.BBWeight == ProfileInfo::MissingValue,
|
||||||
|
"ASSERT:BasicBlock has missing value", &DI);
|
||||||
|
|
||||||
if (DI.inCount > 0) {
|
// Check if this block is a setjmp target.
|
||||||
CheckValue(!Equals(DI.inWeight,DI.BBWeight), "ASSERT:inWeight and BBWeight do not match", &DI);
|
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<CallInst>(&*i)) {
|
||||||
|
Function *F = CI->getCalledFunction();
|
||||||
|
if (F && (F->getNameStr() == "_setjmp")) {
|
||||||
|
isSetJmpTarget = true; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (DI.outCount > 0) {
|
// Check if this block is eventually reaching exit.
|
||||||
CheckValue(!Equals(DI.outWeight,DI.BBWeight), "ASSERT:outWeight and BBWeight do not match", &DI);
|
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<CallInst>(&*i)) {
|
||||||
|
FisVisited.clear();
|
||||||
|
isExitReachable |= exitReachable(CI->getCalledFunction());
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
} 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
|
// mark as visited and recurse into subnodes
|
||||||
BBisVisited.insert(BB);
|
BBisVisited.insert(BB);
|
||||||
for ( succ_const_iterator bbi = succ_begin(BB), bbe = succ_end(BB);
|
for ( succ_const_iterator bbi = succ_begin(BB), bbe = succ_end(BB);
|
||||||
@ -233,7 +304,7 @@ bool ProfileVerifierPass::runOnFunction(Function &F) {
|
|||||||
PI = &getAnalysis<ProfileInfo>();
|
PI = &getAnalysis<ProfileInfo>();
|
||||||
|
|
||||||
if (PI->getExecutionCount(&F) == ProfileInfo::MissingValue) {
|
if (PI->getExecutionCount(&F) == ProfileInfo::MissingValue) {
|
||||||
DEBUG(errs()<<"Function "<<F.getNameStr()<<" has no profile\n");
|
DEBUG(errs() << "Function " << F.getNameStr() << " has no profile\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user