[cfe-commits] r161636 - in /cfe/trunk: lib/StaticAnalyzer/Core/MemRegion.cpp lib/StaticAnalyzer/Core/RegionStore.cpp test/Analysis/ivars.m
Ted Kremenek
kremenek at apple.com
Tue Aug 21 15:51:17 PDT 2012
(catching up)
Really great work. Mostly minor comments inline.
On Aug 9, 2012, at 3:55 PM, Jordan Rose <jordan_rose at apple.com> wrote:
> Author: jrose
> Date: Thu Aug 9 17:55:51 2012
> New Revision: 161636
>
> URL: http://llvm.org/viewvc/llvm-project?rev=161636&view=rev
> Log:
> [analyzer] Cluster bindings in RegionStore by base region.
>
> This should speed up activities that need to access bindings by cluster,
> such as invalidation and dead-bindings cleaning. In some cases all we save
> is the cost of building the region cluster map, but other times we can
> actually avoid traversing the rest of the store.
>
> In casual testing, this produced a speedup of nearly 10% analyzing SQLite,
> with /less/ memory used.
>
> Modified:
> cfe/trunk/lib/StaticAnalyzer/Core/MemRegion.cpp
> cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp
> cfe/trunk/test/Analysis/ivars.m
>
> Modified: cfe/trunk/lib/StaticAnalyzer/Core/MemRegion.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/MemRegion.cpp?rev=161636&r1=161635&r2=161636&view=diff
> ==============================================================================
> --- cfe/trunk/lib/StaticAnalyzer/Core/MemRegion.cpp (original)
> +++ cfe/trunk/lib/StaticAnalyzer/Core/MemRegion.cpp Thu Aug 9 17:55:51 2012
> @@ -1052,10 +1052,17 @@
> case CXXThisRegionKind:
> case StringRegionKind:
> case VarRegionKind:
> - case ObjCIvarRegionKind:
> case CXXTempObjectRegionKind:
> goto Finish;
>
> + case ObjCIvarRegionKind:
> + // This is a little strange, but it's a compromise between
> + // ObjCIvarRegions having unknown compile-time offsets (when using the
> + // non-fragile runtime) and yet still being distinct, non-overlapping
> + // regions. Thus we treat them as "like" base regions for the purposes
> + // of computing offsets.
> + goto Finish;
> +
This is unrelated. Please keep these in a separate commit.
...
> }
> }
> }
> @@ -414,14 +430,11 @@
> template <typename DERIVED>
> class ClusterAnalysis {
> protected:
> - typedef BumpVector<BindingKey> RegionCluster;
> - typedef llvm::DenseMap<const MemRegion *, RegionCluster *> ClusterMap;
> - llvm::DenseMap<const RegionCluster*, unsigned> Visited;
> - typedef SmallVector<std::pair<const MemRegion *, RegionCluster*>, 10>
> - WorkList;
> + typedef llvm::DenseMap<const MemRegion *, const ClusterBindings *> ClusterMap;
> + typedef SmallVector<const MemRegion *, 10> WorkList;
> +
> + llvm::SmallPtrSet<const ClusterBindings *, 16> Visited;
Why the switch from a DenseMap to a SmallPtrSet? Did this show up for some reason as a performance issue?
>
> - BumpVectorContext BVC;
> - ClusterMap ClusterM;
> WorkList WL;
>
> RegionStoreManager &RM;
> @@ -432,6 +445,10 @@
>
> const bool includeGlobals;
>
> + const ClusterBindings *getCluster(const MemRegion *R) {
> + return B.lookup(R);
> + }
> +
> public:
> ClusterAnalysis(RegionStoreManager &rm, ProgramStateManager &StateMgr,
> RegionBindings b, const bool includeGlobals)
> @@ -441,59 +458,36 @@
>
> RegionBindings getRegionBindings() const { return B; }
>
> - RegionCluster &AddToCluster(BindingKey K) {
> - const MemRegion *R = K.getRegion();
> - const MemRegion *baseR = R->getBaseRegion();
> - RegionCluster &C = getCluster(baseR);
> - C.push_back(K, BVC);
> - static_cast<DERIVED*>(this)->VisitAddedToCluster(baseR, C);
> - return C;
> - }
> -
> bool isVisited(const MemRegion *R) {
> - return (bool) Visited[&getCluster(R->getBaseRegion())];
> - }
> -
> - RegionCluster& getCluster(const MemRegion *R) {
> - RegionCluster *&CRef = ClusterM[R];
> - if (!CRef) {
> - void *Mem = BVC.getAllocator().template Allocate<RegionCluster>();
> - CRef = new (Mem) RegionCluster(BVC, 10);
> - }
> - return *CRef;
> + return Visited.count(getCluster(R));
> }
>
> void GenerateClusters() {
> - // Scan the entire set of bindings and make the region clusters.
> + // Scan the entire set of bindings and record the region clusters.
> for (RegionBindings::iterator RI = B.begin(), RE = B.end(); RI != RE; ++RI){
> - RegionCluster &C = AddToCluster(RI.getKey());
> - if (const MemRegion *R = RI.getData().getAsRegion()) {
> - // Generate a cluster, but don't add the region to the cluster
> - // if there aren't any bindings.
> - getCluster(R->getBaseRegion());
> - }
> - if (includeGlobals) {
> - const MemRegion *R = RI.getKey().getRegion();
> - if (isa<NonStaticGlobalSpaceRegion>(R->getMemorySpace()))
> - AddToWorkList(R, C);
> - }
> + const MemRegion *Base = RI.getKey();
> +
> + const ClusterBindings &Cluster = RI.getData();
> + assert(!Cluster.isEmpty() && "Empty clusters should be removed");
> + static_cast<DERIVED*>(this)->VisitAddedToCluster(Base, Cluster);
> +
> + if (includeGlobals)
> + if (isa<NonStaticGlobalSpaceRegion>(Base->getMemorySpace()))
> + AddToWorkList(Base, &Cluster);
> }
> }
>
> - bool AddToWorkList(const MemRegion *R, RegionCluster &C) {
> - if (unsigned &visited = Visited[&C])
> - return false;
> - else
> - visited = 1;
> + bool AddToWorkList(const MemRegion *R, const ClusterBindings *C) {
> + if (C) {
> + if (Visited.count(C))
> + return false;
> + Visited.insert(C);
> + }
If Visited was still a DenseMap this lookup-and-modify would require only one lookup, and a modify of the value in place.
These are minor. The rest of the patch looks straightforward. Great work!
More information about the cfe-commits
mailing list