forked from OSchip/llvm-project
Move the dominator verification code out of special code embedded within
the PassManager code into a regular verifyAnalysis method. Also, reorganize loop verification. Make the LoopPass infrastructure call verifyLoop as needed instead of having LoopInfo::verifyAnalysis check every loop in the function after each looop pass. Add a new command-line argument, -verify-loop-info, to enable the expensive full checking. llvm-svn: 82952
This commit is contained in:
parent
2963777d0c
commit
4dbb301f17
|
@ -734,6 +734,8 @@ public:
|
||||||
|
|
||||||
virtual bool runOnFunction(Function &F);
|
virtual bool runOnFunction(Function &F);
|
||||||
|
|
||||||
|
virtual void verifyAnalysis() const;
|
||||||
|
|
||||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
|
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
|
||||||
AU.setPreservesAll();
|
AU.setPreservesAll();
|
||||||
}
|
}
|
||||||
|
@ -991,6 +993,8 @@ public:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void verifyAnalysis() const;
|
||||||
|
|
||||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
|
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
|
||||||
AU.setPreservesAll();
|
AU.setPreservesAll();
|
||||||
AU.addRequired<DominatorTree>();
|
AU.addRequired<DominatorTree>();
|
||||||
|
|
|
@ -280,9 +280,6 @@ public:
|
||||||
/// verifyPreservedAnalysis -- Verify analysis presreved by pass P.
|
/// verifyPreservedAnalysis -- Verify analysis presreved by pass P.
|
||||||
void verifyPreservedAnalysis(Pass *P);
|
void verifyPreservedAnalysis(Pass *P);
|
||||||
|
|
||||||
/// verifyDomInfo -- Verify dominator information if it is available.
|
|
||||||
void verifyDomInfo(Pass &P, Function &F);
|
|
||||||
|
|
||||||
/// Remove Analysis that is not preserved by the pass
|
/// Remove Analysis that is not preserved by the pass
|
||||||
void removeNotPreservedAnalysis(Pass *P);
|
void removeNotPreservedAnalysis(Pass *P);
|
||||||
|
|
||||||
|
|
|
@ -20,11 +20,22 @@
|
||||||
#include "llvm/Analysis/Dominators.h"
|
#include "llvm/Analysis/Dominators.h"
|
||||||
#include "llvm/Assembly/Writer.h"
|
#include "llvm/Assembly/Writer.h"
|
||||||
#include "llvm/Support/CFG.h"
|
#include "llvm/Support/CFG.h"
|
||||||
|
#include "llvm/Support/CommandLine.h"
|
||||||
#include "llvm/ADT/DepthFirstIterator.h"
|
#include "llvm/ADT/DepthFirstIterator.h"
|
||||||
#include "llvm/ADT/SmallPtrSet.h"
|
#include "llvm/ADT/SmallPtrSet.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
|
// Always verify loopinfo if expensive checking is enabled.
|
||||||
|
#ifdef XDEBUG
|
||||||
|
bool VerifyLoopInfo = true;
|
||||||
|
#else
|
||||||
|
bool VerifyLoopInfo = false;
|
||||||
|
#endif
|
||||||
|
static cl::opt<bool,true>
|
||||||
|
VerifyLoopInfoX("verify-loop-info", cl::location(VerifyLoopInfo),
|
||||||
|
cl::desc("Verify loop info (time consuming)"));
|
||||||
|
|
||||||
char LoopInfo::ID = 0;
|
char LoopInfo::ID = 0;
|
||||||
static RegisterPass<LoopInfo>
|
static RegisterPass<LoopInfo>
|
||||||
X("loops", "Natural Loop Information", true, true);
|
X("loops", "Natural Loop Information", true, true);
|
||||||
|
@ -375,10 +386,20 @@ bool LoopInfo::runOnFunction(Function &) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoopInfo::verifyAnalysis() const {
|
void LoopInfo::verifyAnalysis() const {
|
||||||
|
// LoopInfo is a FunctionPass, but verifying every loop in the function
|
||||||
|
// each time verifyAnalysis is called is very expensive. The
|
||||||
|
// -verify-loop-info option can enable this. In order to perform some
|
||||||
|
// checking by default, LoopPass has been taught to call verifyLoop
|
||||||
|
// manually during loop pass sequences.
|
||||||
|
|
||||||
|
if (!VerifyLoopInfo) return;
|
||||||
|
|
||||||
for (iterator I = begin(), E = end(); I != E; ++I) {
|
for (iterator I = begin(), E = end(); I != E; ++I) {
|
||||||
assert(!(*I)->getParentLoop() && "Top-level loop has a parent!");
|
assert(!(*I)->getParentLoop() && "Top-level loop has a parent!");
|
||||||
(*I)->verifyLoopNest();
|
(*I)->verifyLoopNest();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: check BBMap consistency.
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoopInfo::getAnalysisUsage(AnalysisUsage &AU) const {
|
void LoopInfo::getAnalysisUsage(AnalysisUsage &AU) const {
|
||||||
|
|
|
@ -242,16 +242,24 @@ bool LPPassManager::runOnFunction(Function &F) {
|
||||||
dumpPassInfo(P, MODIFICATION_MSG, ON_LOOP_MSG, "");
|
dumpPassInfo(P, MODIFICATION_MSG, ON_LOOP_MSG, "");
|
||||||
dumpPreservedSet(P);
|
dumpPreservedSet(P);
|
||||||
|
|
||||||
if (!skipThisLoop)
|
if (!skipThisLoop) {
|
||||||
|
// Manually check that this loop is still healthy. This is done
|
||||||
|
// instead of relying on LoopInfo::verifyLoop since LoopInfo
|
||||||
|
// is a function pass and it's really expensive to verify every
|
||||||
|
// loop in the function every time. That level of checking can be
|
||||||
|
// enabled with the -verify-loop-info option.
|
||||||
|
Timer *T = StartPassTimer(LI);
|
||||||
|
CurrentLoop->verifyLoop();
|
||||||
|
StopPassTimer(LI, T);
|
||||||
|
|
||||||
|
// Then call the regular verifyAnalysis functions.
|
||||||
verifyPreservedAnalysis(LP);
|
verifyPreservedAnalysis(LP);
|
||||||
|
}
|
||||||
|
|
||||||
removeNotPreservedAnalysis(P);
|
removeNotPreservedAnalysis(P);
|
||||||
recordAvailableAnalysis(P);
|
recordAvailableAnalysis(P);
|
||||||
removeDeadPasses(P, "", ON_LOOP_MSG);
|
removeDeadPasses(P, "", ON_LOOP_MSG);
|
||||||
|
|
||||||
// If dominator information is available then verify the info if requested.
|
|
||||||
verifyDomInfo(*LP, F);
|
|
||||||
|
|
||||||
if (skipThisLoop)
|
if (skipThisLoop)
|
||||||
// Do not run other passes on this loop.
|
// Do not run other passes on this loop.
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -24,9 +24,20 @@
|
||||||
#include "llvm/Analysis/DominatorInternals.h"
|
#include "llvm/Analysis/DominatorInternals.h"
|
||||||
#include "llvm/Instructions.h"
|
#include "llvm/Instructions.h"
|
||||||
#include "llvm/Support/raw_ostream.h"
|
#include "llvm/Support/raw_ostream.h"
|
||||||
|
#include "llvm/Support/CommandLine.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
|
// Always verify dominfo if expensive checking is enabled.
|
||||||
|
#ifdef XDEBUG
|
||||||
|
bool VerifyDomInfo = true;
|
||||||
|
#else
|
||||||
|
bool VerifyDomInfo = false;
|
||||||
|
#endif
|
||||||
|
static cl::opt<bool,true>
|
||||||
|
VerifyDomInfoX("verify-dom-info", cl::location(VerifyDomInfo),
|
||||||
|
cl::desc("Verify dominator info (time consuming)"));
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// DominatorTree Implementation
|
// DominatorTree Implementation
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
@ -48,6 +59,16 @@ bool DominatorTree::runOnFunction(Function &F) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DominatorTree::verifyAnalysis() const {
|
||||||
|
if (!VerifyDomInfo || true /* fixme */) return;
|
||||||
|
|
||||||
|
Function &F = *getRoot()->getParent();
|
||||||
|
|
||||||
|
DominatorTree OtherDT;
|
||||||
|
OtherDT.getBase().recalculate(F);
|
||||||
|
assert(!compare(OtherDT) && "Invalid DominatorTree info!");
|
||||||
|
}
|
||||||
|
|
||||||
void DominatorTree::print(raw_ostream &OS, const Module *) const {
|
void DominatorTree::print(raw_ostream &OS, const Module *) const {
|
||||||
DT->print(OS);
|
DT->print(OS);
|
||||||
}
|
}
|
||||||
|
@ -87,6 +108,17 @@ char DominanceFrontier::ID = 0;
|
||||||
static RegisterPass<DominanceFrontier>
|
static RegisterPass<DominanceFrontier>
|
||||||
G("domfrontier", "Dominance Frontier Construction", true, true);
|
G("domfrontier", "Dominance Frontier Construction", true, true);
|
||||||
|
|
||||||
|
void DominanceFrontier::verifyAnalysis() const {
|
||||||
|
if (!VerifyDomInfo) return;
|
||||||
|
|
||||||
|
DominatorTree &DT = getAnalysis<DominatorTree>();
|
||||||
|
|
||||||
|
DominanceFrontier OtherDF;
|
||||||
|
const std::vector<BasicBlock*> &DTRoots = DT.getRoots();
|
||||||
|
OtherDF.calculate(DT, DT.getNode(DTRoots[0]));
|
||||||
|
assert(!compare(OtherDF) && "Invalid DominanceFrontier info!");
|
||||||
|
}
|
||||||
|
|
||||||
// NewBB is split and now it has one successor. Update dominace frontier to
|
// NewBB is split and now it has one successor. Update dominace frontier to
|
||||||
// reflect this change.
|
// reflect this change.
|
||||||
void DominanceFrontier::splitBlock(BasicBlock *NewBB) {
|
void DominanceFrontier::splitBlock(BasicBlock *NewBB) {
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
|
|
||||||
|
|
||||||
#include "llvm/PassManagers.h"
|
#include "llvm/PassManagers.h"
|
||||||
|
#include "llvm/Assembly/Writer.h"
|
||||||
#include "llvm/Support/CommandLine.h"
|
#include "llvm/Support/CommandLine.h"
|
||||||
#include "llvm/Support/Timer.h"
|
#include "llvm/Support/Timer.h"
|
||||||
#include "llvm/Module.h"
|
#include "llvm/Module.h"
|
||||||
|
@ -22,7 +23,6 @@
|
||||||
#include "llvm/Support/raw_ostream.h"
|
#include "llvm/Support/raw_ostream.h"
|
||||||
#include "llvm/System/Mutex.h"
|
#include "llvm/System/Mutex.h"
|
||||||
#include "llvm/System/Threading.h"
|
#include "llvm/System/Threading.h"
|
||||||
#include "llvm/Analysis/Dominators.h"
|
|
||||||
#include "llvm-c/Core.h"
|
#include "llvm-c/Core.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
@ -45,16 +45,6 @@ enum PassDebugLevel {
|
||||||
None, Arguments, Structure, Executions, Details
|
None, Arguments, Structure, Executions, Details
|
||||||
};
|
};
|
||||||
|
|
||||||
// Always verify dominfo if expensive checking is enabled.
|
|
||||||
#ifdef XDEBUG
|
|
||||||
bool VerifyDomInfo = true;
|
|
||||||
#else
|
|
||||||
bool VerifyDomInfo = false;
|
|
||||||
#endif
|
|
||||||
static cl::opt<bool,true>
|
|
||||||
VerifyDomInfoX("verify-dom-info", cl::location(VerifyDomInfo),
|
|
||||||
cl::desc("Verify dominator info (time consuming)"));
|
|
||||||
|
|
||||||
static cl::opt<enum PassDebugLevel>
|
static cl::opt<enum PassDebugLevel>
|
||||||
PassDebugging("debug-pass", cl::Hidden,
|
PassDebugging("debug-pass", cl::Hidden,
|
||||||
cl::desc("Print PassManager debugging information"),
|
cl::desc("Print PassManager debugging information"),
|
||||||
|
@ -703,47 +693,13 @@ void PMDataManager::verifyPreservedAnalysis(Pass *P) {
|
||||||
for (AnalysisUsage::VectorType::const_iterator I = PreservedSet.begin(),
|
for (AnalysisUsage::VectorType::const_iterator I = PreservedSet.begin(),
|
||||||
E = PreservedSet.end(); I != E; ++I) {
|
E = PreservedSet.end(); I != E; ++I) {
|
||||||
AnalysisID AID = *I;
|
AnalysisID AID = *I;
|
||||||
if (Pass *AP = findAnalysisPass(AID, true))
|
if (Pass *AP = findAnalysisPass(AID, true)) {
|
||||||
|
|
||||||
|
Timer *T = 0;
|
||||||
|
if (TheTimeInfo) T = TheTimeInfo->passStarted(AP);
|
||||||
AP->verifyAnalysis();
|
AP->verifyAnalysis();
|
||||||
|
if (T) T->stopTimer();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// verifyDomInfo - Verify dominator information if it is available.
|
|
||||||
void PMDataManager::verifyDomInfo(Pass &P, Function &F) {
|
|
||||||
if (!VerifyDomInfo || !P.getResolver())
|
|
||||||
return;
|
|
||||||
|
|
||||||
DominatorTree *DT = P.getAnalysisIfAvailable<DominatorTree>();
|
|
||||||
if (!DT)
|
|
||||||
return;
|
|
||||||
|
|
||||||
DominatorTree OtherDT;
|
|
||||||
OtherDT.getBase().recalculate(F);
|
|
||||||
if (DT->compare(OtherDT)) {
|
|
||||||
errs() << "Dominator Information for " << F.getName() << "\n";
|
|
||||||
errs() << "Pass '" << P.getPassName() << "'\n";
|
|
||||||
errs() << "----- Valid -----\n";
|
|
||||||
OtherDT.dump();
|
|
||||||
errs() << "----- Invalid -----\n";
|
|
||||||
DT->dump();
|
|
||||||
llvm_unreachable("Invalid dominator info");
|
|
||||||
}
|
|
||||||
|
|
||||||
DominanceFrontier *DF = P.getAnalysisIfAvailable<DominanceFrontier>();
|
|
||||||
if (!DF)
|
|
||||||
return;
|
|
||||||
|
|
||||||
DominanceFrontier OtherDF;
|
|
||||||
std::vector<BasicBlock*> DTRoots = DT->getRoots();
|
|
||||||
OtherDF.calculate(*DT, DT->getNode(DTRoots[0]));
|
|
||||||
if (DF->compare(OtherDF)) {
|
|
||||||
errs() << "Dominator Information for " << F.getName() << "\n";
|
|
||||||
errs() << "Pass '" << P.getPassName() << "'\n";
|
|
||||||
errs() << "----- Valid -----\n";
|
|
||||||
OtherDF.dump();
|
|
||||||
errs() << "----- Invalid -----\n";
|
|
||||||
DF->dump();
|
|
||||||
llvm_unreachable("Invalid dominator info");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1384,9 +1340,6 @@ bool FPPassManager::runOnFunction(Function &F) {
|
||||||
removeNotPreservedAnalysis(FP);
|
removeNotPreservedAnalysis(FP);
|
||||||
recordAvailableAnalysis(FP);
|
recordAvailableAnalysis(FP);
|
||||||
removeDeadPasses(FP, F.getName(), ON_FUNCTION_MSG);
|
removeDeadPasses(FP, F.getName(), ON_FUNCTION_MSG);
|
||||||
|
|
||||||
// If dominator information is available then verify the info if requested.
|
|
||||||
verifyDomInfo(*FP, F);
|
|
||||||
}
|
}
|
||||||
return Changed;
|
return Changed;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
; RUN: llc %s -o /dev/null -verify-dom-info
|
; RUN: llc %s -o /dev/null -verify-dom-info -verify-loop-info
|
||||||
%llvm.dbg.anchor.type = type { i32, i32 }
|
%llvm.dbg.anchor.type = type { i32, i32 }
|
||||||
%llvm.dbg.basictype.type = type { i32, { }*, i8*, { }*, i32, i64, i64, i64, i32, i32, i8*, i8* }
|
%llvm.dbg.basictype.type = type { i32, { }*, i8*, { }*, i32, i64, i64, i64, i32, i32, i8*, i8* }
|
||||||
%llvm.dbg.compile_unit.type = type { i32, { }*, i32, i8*, i8*, i8* }
|
%llvm.dbg.compile_unit.type = type { i32, { }*, i32, i8*, i8*, i8* }
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
; RUN: opt < %s -lcssa -disable-output -verify-dom-info
|
; RUN: opt < %s -lcssa -disable-output -verify-dom-info -verify-loop-info
|
||||||
; PR977
|
; PR977
|
||||||
; END.
|
; END.
|
||||||
declare i32 @opost_block()
|
declare i32 @opost_block()
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
; RUN: opt < %s -scalarrepl -loopsimplify -licm -disable-output -verify-dom-info
|
; RUN: opt < %s -scalarrepl -loopsimplify -licm -disable-output -verify-dom-info -verify-loop-info
|
||||||
|
|
||||||
define void @inflate() {
|
define void @inflate() {
|
||||||
entry:
|
entry:
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
; RUN: opt -loop-unswitch %s -disable-output
|
; RUN: opt -loop-unswitch -verify-loop-info -verify-dom-info %s -disable-output
|
||||||
|
|
||||||
; Loop unswitch should be able to unswitch these loops and
|
; Loop unswitch should be able to unswitch these loops and
|
||||||
; preserve LCSSA and LoopSimplify forms.
|
; preserve LCSSA and LoopSimplify forms.
|
||||||
|
|
Loading…
Reference in New Issue