From: Pavel Labath Date: Mon, 19 Aug 2013 15:23:34 +0000 (+0000) Subject: [analyzer] Fix inefficiency in dead symbol removal X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d207f55cd58054aab77edca35b3e7f645738dfe2;p=clang [analyzer] Fix inefficiency in dead symbol removal Summary: ScanReachableSymbols uses a "visited" set to avoid scanning the same object twice. However, it did not use the optimization for LazyCompoundVal objects, which resulted in exponential complexity for long chains of temporary objects. Adding this resulted in a decrease of analysis time from >3h to 3 seconds for some files. Reviewers: jordan_rose CC: cfe-commits Differential Revision: http://llvm-reviews.chandlerc.com/D1398 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@188677 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h index ed1ab8c4cb..96f6242339 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h @@ -798,7 +798,7 @@ CB ProgramState::scanReachableSymbols(const MemRegion * const *beg, /// A Utility class that allows to visit the reachable symbols using a custom /// SymbolVisitor. class ScanReachableSymbols { - typedef llvm::DenseMap VisitedItems; + typedef llvm::DenseSet VisitedItems; VisitedItems visited; ProgramStateRef state; @@ -808,6 +808,7 @@ public: ScanReachableSymbols(ProgramStateRef st, SymbolVisitor& v) : state(st), visitor(v) {} + bool scan(nonloc::LazyCompoundVal val); bool scan(nonloc::CompoundVal val); bool scan(SVal val); bool scan(const MemRegion *R); diff --git a/lib/StaticAnalyzer/Core/ProgramState.cpp b/lib/StaticAnalyzer/Core/ProgramState.cpp index 653b69bf48..fbd3fc526d 100644 --- a/lib/StaticAnalyzer/Core/ProgramState.cpp +++ b/lib/StaticAnalyzer/Core/ProgramState.cpp @@ -526,6 +526,19 @@ ProgramStateRef ProgramStateManager::removeGDM(ProgramStateRef state, void *Key) return getPersistentState(NewState); } +bool ScanReachableSymbols::scan(nonloc::LazyCompoundVal val) { + bool wasVisited = !visited.insert(val.getCVData()).second; + if (wasVisited) + return true; + + StoreManager &StoreMgr = state->getStateManager().getStoreManager(); + // FIXME: We don't really want to use getBaseRegion() here because pointer + // arithmetic doesn't apply, but scanReachableSymbols only accepts base + // regions right now. + const MemRegion *R = val.getRegion()->getBaseRegion(); + return StoreMgr.scanReachableSymbols(val.getStore(), R, *this); +} + bool ScanReachableSymbols::scan(nonloc::CompoundVal val) { for (nonloc::CompoundVal::iterator I=val.begin(), E=val.end(); I!=E; ++I) if (!scan(*I)) @@ -535,10 +548,9 @@ bool ScanReachableSymbols::scan(nonloc::CompoundVal val) { } bool ScanReachableSymbols::scan(const SymExpr *sym) { - unsigned &isVisited = visited[sym]; - if (isVisited) + bool wasVisited = !visited.insert(sym).second; + if (wasVisited) return true; - isVisited = 1; if (!visitor.VisitSymbol(sym)) return false; @@ -570,16 +582,8 @@ bool ScanReachableSymbols::scan(SVal val) { return scan(X->getRegion()); if (Optional X = - val.getAs()) { - StoreManager &StoreMgr = state->getStateManager().getStoreManager(); - // FIXME: We don't really want to use getBaseRegion() here because pointer - // arithmetic doesn't apply, but scanReachableSymbols only accepts base - // regions right now. - if (!StoreMgr.scanReachableSymbols(X->getStore(), - X->getRegion()->getBaseRegion(), - *this)) - return false; - } + val.getAs()) + return scan(*X); if (Optional X = val.getAs()) return scan(X->getLoc()); @@ -600,11 +604,9 @@ bool ScanReachableSymbols::scan(const MemRegion *R) { if (isa(R)) return true; - unsigned &isVisited = visited[R]; - if (isVisited) + bool wasVisited = !visited.insert(R).second; + if (wasVisited) return true; - isVisited = 1; - if (!visitor.VisitMemRegion(R)) return false;