[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