forked from OSchip/llvm-project
Improved ExplodedGraph::Trim to only show nodes reachable from a reverse BFS
from the sources, and to try and generate only a single path from sources to roots. llvm-svn: 48286
This commit is contained in:
parent
ee8d960ed1
commit
576b76a794
|
@ -17,6 +17,7 @@
|
|||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include <vector>
|
||||
#include <list>
|
||||
|
||||
using namespace clang;
|
||||
|
||||
|
@ -89,7 +90,7 @@ ExplodedNodeImpl::NodeGroup::~NodeGroup() {
|
|||
ExplodedGraphImpl* ExplodedGraphImpl::Trim(ExplodedNodeImpl** BeginSources,
|
||||
ExplodedNodeImpl** EndSources) const{
|
||||
|
||||
typedef llvm::DenseSet<ExplodedNodeImpl*> Pass1Ty;
|
||||
typedef llvm::DenseMap<ExplodedNodeImpl*, ExplodedNodeImpl*> Pass1Ty;
|
||||
typedef llvm::DenseMap<ExplodedNodeImpl*, ExplodedNodeImpl*> Pass2Ty;
|
||||
|
||||
Pass1Ty Pass1;
|
||||
|
@ -101,30 +102,58 @@ ExplodedGraphImpl* ExplodedGraphImpl::Trim(ExplodedNodeImpl** BeginSources,
|
|||
|
||||
// Enqueue the source nodes to the first worklist.
|
||||
|
||||
llvm::SmallVector<ExplodedNodeImpl*, 10> WL1;
|
||||
std::list<std::pair<ExplodedNodeImpl*, ExplodedNodeImpl*> > WL1;
|
||||
|
||||
for (ExplodedNodeImpl** I = BeginSources; I != EndSources; ++I)
|
||||
WL1.push_back(*I);
|
||||
WL1.push_back(std::make_pair(*I, *I));
|
||||
|
||||
// Process the worklist.
|
||||
|
||||
while (!WL1.empty()) {
|
||||
|
||||
ExplodedNodeImpl* N = WL1.back();
|
||||
ExplodedNodeImpl* N = WL1.back().first;
|
||||
ExplodedNodeImpl* Src = WL1.back().second;
|
||||
|
||||
WL1.pop_back();
|
||||
|
||||
if (Pass1.count(N))
|
||||
if (Pass1.find(N) != Pass1.end())
|
||||
continue;
|
||||
|
||||
Pass1.insert(N);
|
||||
|
||||
if (N->Preds.empty()) {
|
||||
WL2.push_back(N);
|
||||
continue;
|
||||
bool PredHasSameSource = false;
|
||||
bool VisitPreds = true;
|
||||
|
||||
for (ExplodedNodeImpl** I=N->Preds.begin(), **E=N->Preds.end();
|
||||
I!=E; ++I) {
|
||||
|
||||
Pass1Ty::iterator pi = Pass1.find(*I);
|
||||
|
||||
if (pi == Pass1.end())
|
||||
continue;
|
||||
|
||||
VisitPreds = false;
|
||||
|
||||
if (pi->second == Src) {
|
||||
PredHasSameSource = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (ExplodedNodeImpl** I=N->Preds.begin(), **E=N->Preds.end(); I!=E; ++I)
|
||||
WL1.push_back(*I);
|
||||
if (VisitPreds || !PredHasSameSource) {
|
||||
|
||||
Pass1[N] = Src;
|
||||
|
||||
if (N->Preds.empty()) {
|
||||
WL2.push_back(N);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
Pass1[N] = NULL;
|
||||
|
||||
if (VisitPreds)
|
||||
for (ExplodedNodeImpl** I=N->Preds.begin(), **E=N->Preds.end();
|
||||
I!=E; ++I)
|
||||
WL1.push_front(std::make_pair(*I, Src));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -182,8 +211,12 @@ ExplodedGraphImpl* ExplodedGraphImpl::Trim(ExplodedNodeImpl** BeginSources,
|
|||
|
||||
// Enqueue nodes to the worklist that were marked during pass 1.
|
||||
|
||||
if (Pass1.count(*I))
|
||||
WL2.push_back(*I);
|
||||
Pass1Ty::iterator pi = Pass1.find(*I);
|
||||
|
||||
if (pi == Pass1.end() || pi->second == NULL)
|
||||
continue;
|
||||
|
||||
WL2.push_back(*I);
|
||||
}
|
||||
|
||||
if (N->isSink())
|
||||
|
|
|
@ -1805,23 +1805,49 @@ struct VISIBILITY_HIDDEN DOTGraphTraits<GRExprEngine::NodeTy*> :
|
|||
#endif
|
||||
|
||||
#ifndef NDEBUG
|
||||
|
||||
template <typename ITERATOR>
|
||||
GRExprEngine::NodeTy* GetGraphNode(ITERATOR I) { return *I; }
|
||||
|
||||
template <>
|
||||
GRExprEngine::NodeTy*
|
||||
GetGraphNode<llvm::DenseMap<GRExprEngine::NodeTy*, Expr*>::iterator>
|
||||
(llvm::DenseMap<GRExprEngine::NodeTy*, Expr*>::iterator I) {
|
||||
return I->first;
|
||||
}
|
||||
|
||||
template <typename ITERATOR>
|
||||
static void AddSources(llvm::SmallVector<GRExprEngine::NodeTy*, 10>& Sources,
|
||||
ITERATOR I, ITERATOR E) {
|
||||
ITERATOR I, ITERATOR E) {
|
||||
|
||||
for ( ; I != E; ++I )
|
||||
Sources.push_back(*I);
|
||||
llvm::SmallPtrSet<void*,10> CachedSources;
|
||||
|
||||
for ( ; I != E; ++I ) {
|
||||
GRExprEngine::NodeTy* N = GetGraphNode(I);
|
||||
void* p = N->getLocation().getRawData();
|
||||
|
||||
if (CachedSources.count(p))
|
||||
continue;
|
||||
|
||||
CachedSources.insert(p);
|
||||
|
||||
Sources.push_back(N);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void GRExprEngine::ViewGraph(bool trim) {
|
||||
#ifndef NDEBUG
|
||||
if (trim) {
|
||||
llvm::SmallVector<NodeTy*, 10> Sources;
|
||||
AddSources(Sources, null_derefs_begin(), null_derefs_end());
|
||||
AddSources(Sources, undef_derefs_begin(), undef_derefs_end());
|
||||
llvm::SmallVector<NodeTy*, 10> Src;
|
||||
AddSources(Src, null_derefs_begin(), null_derefs_end());
|
||||
AddSources(Src, undef_derefs_begin(), undef_derefs_end());
|
||||
AddSources(Src, explicit_bad_divides_begin(), explicit_bad_divides_end());
|
||||
AddSources(Src, undef_results_begin(), undef_results_end());
|
||||
AddSources(Src, bad_calls_begin(), bad_calls_end());
|
||||
AddSources(Src, undef_arg_begin(), undef_arg_end());
|
||||
|
||||
ViewGraph(&Sources[0], &Sources[0]+Sources.size());
|
||||
ViewGraph(&Src[0], &Src[0]+Src.size());
|
||||
}
|
||||
else {
|
||||
GraphPrintCheckerState = this;
|
||||
|
|
|
@ -101,7 +101,7 @@ unsigned RunGRSimpleVals(CFG& cfg, FunctionDecl& FD, ASTContext& Ctx,
|
|||
CheckerState->setTransferFunctions(GRSV);
|
||||
|
||||
// Execute the worklist algorithm.
|
||||
Eng.ExecuteWorkList(50000);
|
||||
Eng.ExecuteWorkList(100000);
|
||||
|
||||
SourceManager& SrcMgr = Ctx.getSourceManager();
|
||||
|
||||
|
|
Loading…
Reference in New Issue