[cfe-commits] r98144 - /cfe/trunk/lib/Checker/RegionStore.cpp

Ted Kremenek kremenek at apple.com
Tue Mar 9 23:20:03 PST 2010


Author: kremenek
Date: Wed Mar 10 01:20:03 2010
New Revision: 98144

URL: http://llvm.org/viewvc/llvm-project?rev=98144&view=rev
Log:
Refactor RegionStore::RemoveDeadBindings to use the same core
cluster analysis algorithm as RegionStore::InvalidateRegions().

Beyond simplifying the algorithm significantly, we no longer
need to build subregion maps in RemoveDeadBindings().  This
and other changes cause a significant speedup: the time to
analyze sqlite3.c (single core) drops by 14%.

Modified:
    cfe/trunk/lib/Checker/RegionStore.cpp

Modified: cfe/trunk/lib/Checker/RegionStore.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Checker/RegionStore.cpp?rev=98144&r1=98143&r2=98144&view=diff
==============================================================================
--- cfe/trunk/lib/Checker/RegionStore.cpp (original)
+++ cfe/trunk/lib/Checker/RegionStore.cpp Wed Mar 10 01:20:03 2010
@@ -41,25 +41,25 @@
   enum Kind { Direct = 0x0, Default = 0x1 };
 private:
   llvm ::PointerIntPair<const MemRegion*, 1> P;
-  uint64_t Offset;  
-  
+  uint64_t Offset;
+
   explicit BindingKey(const MemRegion *r, uint64_t offset, Kind k)
     : P(r, (unsigned) k), Offset(offset) { assert(r); }
 public:
-  
+
   bool isDefault() const { return P.getInt() == Default; }
   bool isDirect() const { return P.getInt() == Direct; }
-  
+
   const MemRegion *getRegion() const { return P.getPointer(); }
   uint64_t getOffset() const { return Offset; }
-  
+
   void Profile(llvm::FoldingSetNodeID& ID) const {
     ID.AddPointer(P.getOpaqueValue());
     ID.AddInteger(Offset);
   }
-  
+
   static BindingKey Make(const MemRegion *R, Kind k);
-  
+
   bool operator<(const BindingKey &X) const {
     if (P.getOpaqueValue() < X.P.getOpaqueValue())
       return true;
@@ -67,16 +67,16 @@
       return false;
     return Offset < X.Offset;
   }
-  
+
   bool operator==(const BindingKey &X) const {
     return P.getOpaqueValue() == X.P.getOpaqueValue() &&
            Offset == X.Offset;
   }
-};    
+};
 } // end anonymous namespace
 
 namespace llvm {
-  static inline 
+  static inline
   llvm::raw_ostream& operator<<(llvm::raw_ostream& os, BindingKey K) {
     os << '(' << K.getRegion() << ',' << K.getOffset()
        << ',' << (K.isDirect() ? "direct" : "default")
@@ -174,7 +174,7 @@
   void process(llvm::SmallVectorImpl<const SubRegion*> &WL, const SubRegion *R);
 
   ~RegionStoreSubRegionMap() {}
-  
+
   const Set *getSubRegions(const MemRegion *Parent) const {
     Map::const_iterator I = M.find(Parent);
     return I == M.end() ? NULL : &I->second;
@@ -196,11 +196,11 @@
   }
 };
 
-  
+
 class RegionStoreManager : public StoreManager {
   const RegionStoreFeatures Features;
   RegionBindings::Factory RBFactory;
-  
+
   typedef llvm::DenseMap<Store, RegionStoreSubRegionMap*> SMCache;
   SMCache SC;
 
@@ -226,10 +226,10 @@
   /// getDefaultBinding - Returns an SVal* representing an optional default
   ///  binding associated with a region and its subregions.
   Optional<SVal> getDefaultBinding(RegionBindings B, const MemRegion *R);
-  
+
   /// setImplicitDefaultValue - Set the default binding for the provided
   ///  MemRegion to the value implicitly defined for compound literals when
-  ///  the value is not specified.  
+  ///  the value is not specified.
   Store setImplicitDefaultValue(Store store, const MemRegion *R, QualType T);
 
   /// ArrayToPointer - Emulates the "decay" of an array to a pointer
@@ -250,11 +250,11 @@
   // Binding values to regions.
   //===-------------------------------------------------------------------===//
 
-  Store InvalidateRegion(Store store, const MemRegion *R, const Expr *E, 
+  Store InvalidateRegion(Store store, const MemRegion *R, const Expr *E,
                          unsigned Count, InvalidatedSymbols *IS) {
     return RegionStoreManager::InvalidateRegions(store, &R, &R+1, E, Count, IS);
   }
-  
+
   Store InvalidateRegions(Store store,
                           const MemRegion * const *Begin,
                           const MemRegion * const *End,
@@ -262,7 +262,7 @@
                           InvalidatedSymbols *IS);
 
 public:   // Made public for helper classes.
-  
+
   void RemoveSubRegionBindings(RegionBindings &B, const MemRegion *R,
                                RegionStoreSubRegionMap &M);
 
@@ -270,17 +270,17 @@
 
   RegionBindings Add(RegionBindings B, const MemRegion *R,
                      BindingKey::Kind k, SVal V);
-  
+
   const SVal *Lookup(RegionBindings B, BindingKey K);
   const SVal *Lookup(RegionBindings B, const MemRegion *R, BindingKey::Kind k);
 
   RegionBindings Remove(RegionBindings B, BindingKey K);
   RegionBindings Remove(RegionBindings B, const MemRegion *R,
                         BindingKey::Kind k);
-  
+
   RegionBindings Remove(RegionBindings B, const MemRegion *R) {
     return Remove(Remove(B, R, BindingKey::Direct), R, BindingKey::Default);
-  }    
+  }
 
   Store Remove(Store store, BindingKey K);
 
@@ -306,7 +306,7 @@
   Store KillStruct(Store store, const TypedRegion* R);
 
   Store Remove(Store store, Loc LV);
-  
+
 
   //===------------------------------------------------------------------===//
   // Loading values from regions.
@@ -373,7 +373,7 @@
   //===------------------------------------------------------------------===//
 
   const GRState *setExtent(const GRState *state,const MemRegion* R,SVal Extent);
-  DefinedOrUnknownSVal getSizeInElements(const GRState *state, 
+  DefinedOrUnknownSVal getSizeInElements(const GRState *state,
                                          const MemRegion* R, QualType EleTy);
 
   //===------------------------------------------------------------------===//
@@ -699,7 +699,7 @@
                             StateMgr.getValueManager());
   return W.InvalidateRegions(store, I, E, Ex, Count);
 }
-  
+
 //===----------------------------------------------------------------------===//
 // Extents for regions.
 //===----------------------------------------------------------------------===//
@@ -710,7 +710,7 @@
 
   switch (R->getKind()) {
     case MemRegion::CXXThisRegionKind:
-      assert(0 && "Cannot get size of 'this' region");      
+      assert(0 && "Cannot get size of 'this' region");
     case MemRegion::GenericMemSpaceRegionKind:
     case MemRegion::StackLocalsSpaceRegionKind:
     case MemRegion::StackArgumentsSpaceRegionKind:
@@ -743,7 +743,7 @@
       if (!CI)
         return UnknownVal();
 
-      CharUnits RegionSize = 
+      CharUnits RegionSize =
         CharUnits::fromQuantity(CI->getValue().getSExtValue());
       CharUnits EleSize = getContext().getTypeSizeInChars(EleTy);
       assert(RegionSize % EleSize == 0);
@@ -864,7 +864,7 @@
     // Not yet handled.
     case MemRegion::VarRegionKind:
     case MemRegion::StringRegionKind: {
-      
+
     }
     // Fall-through.
     case MemRegion::CompoundLiteralRegionKind:
@@ -908,13 +908,13 @@
         MRMgr.getElementRegion(ER->getElementType(), NewIdx,
                                ER->getSuperRegion(), getContext());
       return ValMgr.makeLoc(NewER);
-    }    
+    }
     if (0 == Base->getValue()) {
       const MemRegion* NewER =
         MRMgr.getElementRegion(ER->getElementType(), R,
                                ER->getSuperRegion(), getContext());
-      return ValMgr.makeLoc(NewER);      
-    }    
+      return ValMgr.makeLoc(NewER);
+    }
   }
 
   return UnknownVal();
@@ -924,10 +924,10 @@
 // Loading values from regions.
 //===----------------------------------------------------------------------===//
 
-Optional<SVal> RegionStoreManager::getDirectBinding(RegionBindings B, 
+Optional<SVal> RegionStoreManager::getDirectBinding(RegionBindings B,
                                                  const MemRegion *R) {
   if (const SVal *V = Lookup(B, R, BindingKey::Direct))
-    return *V;  
+    return *V;
 
   return Optional<SVal>();
 }
@@ -947,10 +947,10 @@
 
 Optional<SVal> RegionStoreManager::getBinding(RegionBindings B,
                                               const MemRegion *R) {
-  
+
   if (Optional<SVal> V = getDirectBinding(B, R))
     return V;
-  
+
   return getDefaultBinding(B, R);
 }
 
@@ -988,12 +988,12 @@
 SVal RegionStoreManager::Retrieve(Store store, Loc L, QualType T) {
   assert(!isa<UnknownVal>(L) && "location unknown");
   assert(!isa<UndefinedVal>(L) && "location undefined");
-  
+
   // FIXME: Is this even possible?  Shouldn't this be treated as a null
   //  dereference at a higher level?
   if (isa<loc::ConcreteInt>(L))
     return UndefinedVal();
-  
+
   const MemRegion *MR = cast<loc::MemRegionVal>(L).getRegion();
 
   if (isa<AllocaRegion>(MR) || isa<SymbolicRegion>(MR))
@@ -1053,7 +1053,7 @@
     // bound regions (e.g., several bound bytes), or could be a subset of
     // a larger value.
     return CastRetrievedVal(RetrieveElement(store, ER), ER, T, false);
-  }    
+  }
 
   if (const ObjCIvarRegion *IVR = dyn_cast<ObjCIvarRegion>(R)) {
     // FIXME: Here we actually perform an implicit conversion from the loaded
@@ -1071,7 +1071,7 @@
     // that blow past the extent of the variable.  If the address of the
     // variable is reinterpretted, it is possible we stored a different value
     // that could fit within the variable.  Either we need to cast these when
-    // storing them or reinterpret them lazily (as we do here).    
+    // storing them or reinterpret them lazily (as we do here).
     return CastRetrievedVal(RetrieveVar(store, VR), VR, T, false);
   }
 
@@ -1120,7 +1120,7 @@
       return std::make_pair(X.first,
                             MRMgr.getFieldRegionWithSuper(FR, X.second));
   }
-  // The NULL MemRegion indicates an non-existent lazy binding. A NULL Store is 
+  // The NULL MemRegion indicates an non-existent lazy binding. A NULL Store is
   // possible for a valid lazy binding.
   return std::make_pair((Store) 0, (const MemRegion *) 0);
 }
@@ -1136,13 +1136,13 @@
 
   // Check if the region is an element region of a string literal.
   if (const StringRegion *StrR=dyn_cast<StringRegion>(superR)) {
-    // FIXME: Handle loads from strings where the literal is treated as 
+    // FIXME: Handle loads from strings where the literal is treated as
     // an integer, e.g., *((unsigned int*)"hello")
     ASTContext &Ctx = getContext();
     QualType T = Ctx.getAsArrayType(StrR->getValueType(Ctx))->getElementType();
     if (T != Ctx.getCanonicalType(R->getElementType()))
       return UnknownVal();
-    
+
     const StringLiteral *Str = StrR->getStringLiteral();
     SVal Idx = R->getIndex();
     if (nonloc::ConcreteInt *CI = dyn_cast<nonloc::ConcreteInt>(&Idx)) {
@@ -1179,7 +1179,7 @@
     // Other cases: give up.
     return UnknownVal();
   }
-    
+
   return RetrieveFieldOrElementCommon(store, R, R->getElementType(), superR);
 }
 
@@ -1292,8 +1292,8 @@
   const VarDecl *VD = R->getDecl();
   QualType T = VD->getType();
   const MemSpaceRegion *MS = R->getMemorySpace();
-  
-  if (isa<UnknownSpaceRegion>(MS) || 
+
+  if (isa<UnknownSpaceRegion>(MS) ||
       isa<StackArgumentsSpaceRegion>(MS))
     return ValMgr.getRegionValueSymbolVal(R);
 
@@ -1306,9 +1306,9 @@
     if (T->isPointerType())
       return ValMgr.makeNull();
 
-    return UnknownVal();    
+    return UnknownVal();
   }
-    
+
   return UndefinedVal();
 }
 
@@ -1426,7 +1426,7 @@
     // Binding directly to a symbolic region should be treated as binding
     // to element 0.
     QualType T = SR->getSymbol()->getType(getContext());
-    
+
     // FIXME: Is this the right way to handle symbols that are references?
     if (const PointerType *PT = T->getAs<PointerType>())
       T = PT->getPointeeType();
@@ -1441,7 +1441,7 @@
   return Add(B, R, BindingKey::Direct, V).getRoot();
 }
 
-Store RegionStoreManager::BindDecl(Store store, const VarRegion *VR, 
+Store RegionStoreManager::BindDecl(Store store, const VarRegion *VR,
                                    SVal InitVal) {
 
   QualType T = VR->getDecl()->getType();
@@ -1484,19 +1484,19 @@
 
   return Add(B, R, BindingKey::Default, V).getRoot();
 }
-  
-Store RegionStoreManager::BindArray(Store store, const TypedRegion* R, 
+
+Store RegionStoreManager::BindArray(Store store, const TypedRegion* R,
                                     SVal Init) {
-  
+
   ASTContext &Ctx = getContext();
   const ArrayType *AT =
     cast<ArrayType>(Ctx.getCanonicalType(R->getValueType(Ctx)));
-  QualType ElementTy = AT->getElementType();  
+  QualType ElementTy = AT->getElementType();
   Optional<uint64_t> Size;
-  
+
   if (const ConstantArrayType* CAT = dyn_cast<ConstantArrayType>(AT))
     Size = CAT->getSize().getZExtValue();
-    
+
   // Check if the init expr is a StringLiteral.
   if (isa<loc::MemRegionVal>(Init)) {
     const MemRegion* InitR = cast<loc::MemRegionVal>(Init).getRegion();
@@ -1508,11 +1508,11 @@
     // Copy bytes from the string literal into the target array. Trailing bytes
     // in the array that are not covered by the string literal are initialized
     // to zero.
-    
+
     // We assume that string constants are bound to
     // constant arrays.
     uint64_t size = Size.getValue();
-    
+
     for (uint64_t i = 0; i < size; ++i, ++j) {
       if (j >= len)
         break;
@@ -1533,10 +1533,10 @@
     return CopyLazyBindings(*LCV, store, R);
 
   // Remaining case: explicit compound values.
-  
+
   if (Init.isUnknown())
-    return setImplicitDefaultValue(store, R, ElementTy);    
-  
+    return setImplicitDefaultValue(store, R, ElementTy);
+
   nonloc::CompoundVal& CV = cast<nonloc::CompoundVal>(Init);
   nonloc::CompoundVal::iterator VI = CV.begin(), VE = CV.end();
   uint64_t i = 0;
@@ -1652,14 +1652,14 @@
 BindingKey BindingKey::Make(const MemRegion *R, Kind k) {
   if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) {
     const RegionRawOffset &O = ER->getAsRawOffset();
-    
+
     if (O.getRegion())
       return BindingKey(O.getRegion(), O.getByteOffset(), k);
-    
+
     // FIXME: There are some ElementRegions for which we cannot compute
     // raw offsets yet, including regions with symbolic offsets.
   }
-  
+
   return BindingKey(R, 0, k);
 }
 
@@ -1699,7 +1699,7 @@
 //===----------------------------------------------------------------------===//
 // State pruning.
 //===----------------------------------------------------------------------===//
-  
+
 Store RegionStoreManager::RemoveDeadBindings(Store store, Stmt* Loc,
                                              SymbolReaper& SymReaper,
                            llvm::SmallVectorImpl<const MemRegion*>& RegionRoots)
@@ -1711,48 +1711,48 @@
   // The backmap from regions to subregions.
   llvm::OwningPtr<RegionStoreSubRegionMap>
     SubRegions(getRegionStoreSubRegionMap(store));
-  
+
   // Do a pass over the regions in the store.  For VarRegions we check if
   // the variable is still live and if so add it to the list of live roots.
   // For other regions we populate our region backmap.
   llvm::SmallVector<const MemRegion*, 10> IntermediateRoots;
-  
+
   // Scan the direct bindings for "intermediate" roots.
   for (RegionBindings::iterator I = B.begin(), E = B.end(); I != E; ++I) {
     const MemRegion *R = I.getKey().getRegion();
     IntermediateRoots.push_back(R);
   }
-  
+
   // Process the "intermediate" roots to find if they are referenced by
   // real roots.
   llvm::SmallVector<RBDNode, 10> WorkList;
   llvm::SmallVector<RBDNode, 10> Postponed;
 
   llvm::DenseSet<const MemRegion*> IntermediateVisited;
-  
+
   while (!IntermediateRoots.empty()) {
     const MemRegion* R = IntermediateRoots.back();
     IntermediateRoots.pop_back();
-    
+
     if (IntermediateVisited.count(R))
       continue;
     IntermediateVisited.insert(R);
-    
+
     if (const VarRegion* VR = dyn_cast<VarRegion>(R)) {
       if (SymReaper.isLive(Loc, VR))
         WorkList.push_back(std::make_pair(store, VR));
       continue;
     }
-    
+
     if (const SymbolicRegion* SR = dyn_cast<SymbolicRegion>(R)) {
-      llvm::SmallVectorImpl<RBDNode> &Q =      
+      llvm::SmallVectorImpl<RBDNode> &Q =
         SymReaper.isLive(SR->getSymbol()) ? WorkList : Postponed;
-      
+
         Q.push_back(std::make_pair(store, SR));
 
       continue;
     }
-    
+
       // Add the super region for R to the worklist if it is a subregion.
     if (const SubRegion* superR =
         dyn_cast<SubRegion>(cast<SubRegion>(R)->getSuperRegion()))
@@ -1765,14 +1765,14 @@
     WorkList.push_back(std::make_pair(store, *I));
   }
   RegionRoots.clear();
-  
+
   llvm::DenseSet<RBDNode> Visited;
-  
+
 tryAgain:
   while (!WorkList.empty()) {
     RBDNode N = WorkList.back();
     WorkList.pop_back();
-    
+
     // Have we visited this node before?
     if (Visited.count(N))
       continue;
@@ -1780,10 +1780,10 @@
 
     const MemRegion *R = N.second;
     Store store_N = N.first;
-    
+
     // Enqueue subregions.
     RegionStoreSubRegionMap *M;
-      
+
     if (store == store_N)
       M = SubRegions.get();
     else {
@@ -1805,7 +1805,7 @@
         // If 'R' is a field or an element, we want to keep the bindings
         // for the other fields and elements around.  The reason is that
         // pointer arithmetic can get us to the other fields or elements.
-        assert(isa<FieldRegion>(R) || isa<ElementRegion>(R) 
+        assert(isa<FieldRegion>(R) || isa<ElementRegion>(R)
                || isa<ObjCIvarRegion>(R));
         WorkList.push_back(std::make_pair(store_N, superR));
       }
@@ -1815,7 +1815,7 @@
     // should continue to track that symbol.
     if (const SymbolicRegion *SymR = dyn_cast<SymbolicRegion>(R))
       SymReaper.markLive(SymR->getSymbol());
-    
+
     // For BlockDataRegions, enqueue the VarRegions for variables marked
     // with __block (passed-by-reference).
     // via BlockDeclRefExprs.
@@ -1832,7 +1832,7 @@
     }
 
     RegionBindings B_N = GetRegionBindings(store_N);
-    
+
     // Get the data binding for R (if any).
     Optional<SVal> V = getBinding(B_N, R);
 
@@ -1840,7 +1840,7 @@
       // Check for lazy bindings.
       if (const nonloc::LazyCompoundVal *LCV =
             dyn_cast<nonloc::LazyCompoundVal>(V.getPointer())) {
-      
+
         const LazyCompoundValData *D = LCV->getCVData();
         WorkList.push_back(std::make_pair(D->getStore(), D->getRegion()));
       }
@@ -1849,18 +1849,18 @@
         for (SVal::symbol_iterator SI=V->symbol_begin(), SE=V->symbol_end();
              SI!=SE;++SI)
           SymReaper.markLive(*SI);
-        
+
         // If V is a region, then add it to the worklist.
         if (const MemRegion *RX = V->getAsRegion())
           WorkList.push_back(std::make_pair(store_N, RX));
       }
     }
   }
-  
+
   // See if any postponed SymbolicRegions are actually live now, after
   // having done a scan.
   for (llvm::SmallVectorImpl<RBDNode>::iterator I = Postponed.begin(),
-       E = Postponed.end() ; I != E ; ++I) {    
+       E = Postponed.end() ; I != E ; ++I) {
     if (const SymbolicRegion *SR = cast_or_null<SymbolicRegion>(I->second)) {
       if (SymReaper.isLive(SR->getSymbol())) {
         WorkList.push_back(*I);
@@ -1868,10 +1868,10 @@
       }
     }
   }
-  
+
   if (!WorkList.empty())
     goto tryAgain;
-  
+
   // We have now scanned the store, marking reachable regions and symbols
   // as live.  We now remove all the regions that are dead from the store
   // as well as update DSymbols with the set symbols that are now dead.





More information about the cfe-commits mailing list