Static Value-Flow Analysis
Public Types | Public Member Functions | Static Public Member Functions | Private Member Functions | Private Attributes | List of all members
SVF::PersistentPointsToCache< Data > Class Template Reference

#include <PersistentPointsToCache.h>

Public Types

typedef Map< Data, PointsToIDPTSToIDMap
 
typedef std::function< Data(const Data &, const Data &)> DataOp
 
typedef Map< std::pair< PointsToID, PointsToID >, PointsToIDOpCache
 

Public Member Functions

 PersistentPointsToCache (void)
 
void clear ()
 Clear the cache. More...
 
void reset (void)
 Resets the cache removing everything except the emptyData it was initialised with. More...
 
void remapAllPts (void)
 Remaps all points-to sets stored in the cache to the current mapping. More...
 
PointsToID emplacePts (const Data &pts)
 
const Data & getActualPts (PointsToID id) const
 Returns the points-to set which id represents. id must be stored in the cache. More...
 
PointsToID unionPts (PointsToID lhs, PointsToID rhs)
 Unions lhs and rhs and returns their union's ID. More...
 
PointsToID complementPts (PointsToID lhs, PointsToID rhs)
 Relatively complements lhs and rhs (lhs \ rhs) and returns it's ID. More...
 
PointsToID intersectPts (PointsToID lhs, PointsToID rhs)
 Intersects lhs and rhs (lhs AND rhs) and returns the intersection's ID. More...
 
void printStats (const std::string subtitle) const
 Print statistics on operations and points-to set numbers. More...
 
Map< Data, unsigned > getAllPts (void)
 

Static Public Member Functions

static PointsToID emptyPointsToId (void)
 

Private Member Functions

PointsToID newPointsToId (void)
 
PointsToID opPts (PointsToID lhs, PointsToID rhs, const DataOp &dataOp, OpCache &opCache, bool commutative, bool &opPerformed)
 
void initStats (void)
 Initialises statistics variables to 0. More...
 

Private Attributes

std::vector< std::unique_ptr< Data > > idToPts
 
PTSToIDMap ptsToId
 Maps points-to sets to their corresponding ID. More...
 
OpCache unionCache
 Maps two IDs to their union. Keys must be sorted. More...
 
OpCache complementCache
 Maps two IDs to their relative complement. More...
 
OpCache intersectionCache
 Maps two IDs to their intersection. Keys must be sorted. More...
 
PointsToID idCounter
 Used to generate new PointsToIDs. Any non-zero is valid. More...
 
u64_t totalUnions
 
u64_t uniqueUnions
 
u64_t propertyUnions
 
u64_t lookupUnions
 
u64_t preemptiveUnions
 
u64_t totalComplements
 
u64_t uniqueComplements
 
u64_t propertyComplements
 
u64_t lookupComplements
 
u64_t preemptiveComplements
 
u64_t totalIntersections
 
u64_t uniqueIntersections
 
u64_t propertyIntersections
 
u64_t lookupIntersections
 
u64_t preemptiveIntersections
 

Detailed Description

template<typename Data>
class SVF::PersistentPointsToCache< Data >

Persistent points-to set store. Can be used as a backing for points-to data structures like PointsToDS and PointsToDFDS. Hides points-to sets and union operations from users and hands out PointsToIDs. Points-to sets are interned, and union operations are lazy and hash-consed.

Definition at line 32 of file PersistentPointsToCache.h.

Member Typedef Documentation

◆ DataOp

template<typename Data >
typedef std::function<Data(const Data &, const Data &)> SVF::PersistentPointsToCache< Data >::DataOp

Definition at line 36 of file PersistentPointsToCache.h.

◆ OpCache

template<typename Data >
typedef Map<std::pair<PointsToID, PointsToID>, PointsToID> SVF::PersistentPointsToCache< Data >::OpCache

Definition at line 38 of file PersistentPointsToCache.h.

◆ PTSToIDMap

template<typename Data >
typedef Map<Data, PointsToID> SVF::PersistentPointsToCache< Data >::PTSToIDMap

Definition at line 35 of file PersistentPointsToCache.h.

Constructor & Destructor Documentation

◆ PersistentPointsToCache()

template<typename Data >
SVF::PersistentPointsToCache< Data >::PersistentPointsToCache ( void  )
inline

Definition at line 46 of file PersistentPointsToCache.h.

46  : idCounter(1)
47  {
48  idToPts.push_back(std::make_unique<Data>());
49  ptsToId[Data()] = emptyPointsToId();
50 
51  initStats();
52  }
std::vector< std::unique_ptr< Data > > idToPts
PTSToIDMap ptsToId
Maps points-to sets to their corresponding ID.
static PointsToID emptyPointsToId(void)
void initStats(void)
Initialises statistics variables to 0.
PointsToID idCounter
Used to generate new PointsToIDs. Any non-zero is valid.

Member Function Documentation

◆ clear()

template<typename Data >
void SVF::PersistentPointsToCache< Data >::clear ( )
inline

Clear the cache.

Definition at line 55 of file PersistentPointsToCache.h.

56  {
57  idToPts.clear();
58  ptsToId.clear();
59 
60  unionCache.clear();
61  complementCache.clear();
62  intersectionCache.clear();
63  }
OpCache intersectionCache
Maps two IDs to their intersection. Keys must be sorted.
OpCache unionCache
Maps two IDs to their union. Keys must be sorted.
OpCache complementCache
Maps two IDs to their relative complement.

◆ complementPts()

template<typename Data >
PointsToID SVF::PersistentPointsToCache< Data >::complementPts ( PointsToID  lhs,
PointsToID  rhs 
)
inline

Relatively complements lhs and rhs (lhs \ rhs) and returns it's ID.

Definition at line 173 of file PersistentPointsToCache.h.

174  {
175  static const DataOp complementOp = [](const Data &lhs, const Data &rhs)
176  {
177  return lhs - rhs;
178  };
179 
181 
182  // Property cases.
183  // x - x
184  if (lhs == rhs)
185  {
187  return emptyPointsToId();
188  }
189 
190  // x - EMPTY_SET
191  if (rhs == emptyPointsToId())
192  {
194  return lhs;
195  }
196 
197  // EMPTY_SET - x
198  if (lhs == emptyPointsToId())
199  {
201  return emptyPointsToId();
202  }
203 
204  bool opPerformed = false;
205  const PointsToID result = opPts(lhs, rhs, complementOp, complementCache, false, opPerformed);
206 
207  if (opPerformed)
208  {
210 
211  // We performed lhs - rhs = result, so...
212  if (result != emptyPointsToId())
213  {
214  // result AND rhs = EMPTY_SET,
215  intersectionCache[std::minmax(result, rhs)] = emptyPointsToId();
218 
219  // and result AND lhs = result,
220  intersectionCache[std::minmax(result, lhs)] = result;
223 
224  // and result - rhs = result.
225  complementCache[std::make_pair(result, rhs)] = result;
228  }
229  }
230  else ++lookupComplements;
231 
232  return result;
233  }
std::function< Data(const Data &, const Data &)> DataOp
PointsToID opPts(PointsToID lhs, PointsToID rhs, const DataOp &dataOp, OpCache &opCache, bool commutative, bool &opPerformed)
unsigned PointsToID
Definition: GeneralType.h:63

◆ emplacePts()

template<typename Data >
PointsToID SVF::PersistentPointsToCache< Data >::emplacePts ( const Data &  pts)
inline

If pts is not in the PersistentPointsToCache, inserts it, assigns an ID, and returns that ID. If it is, then the ID is returned.

Definition at line 91 of file PersistentPointsToCache.h.

92  {
93  // Is it already in the cache?
94  typename PTSToIDMap::const_iterator foundId = ptsToId.find(pts);
95  if (foundId != ptsToId.end()) return foundId->second;
96 
97  // Otherwise, insert it.
99  idToPts.push_back(std::make_unique<Data>(pts));
100  ptsToId[pts] = id;
101 
102  return id;
103  }

◆ emptyPointsToId()

template<typename Data >
static PointsToID SVF::PersistentPointsToCache< Data >::emptyPointsToId ( void  )
inlinestatic

Definition at line 40 of file PersistentPointsToCache.h.

41  {
42  return 0;
43  };

◆ getActualPts()

template<typename Data >
const Data& SVF::PersistentPointsToCache< Data >::getActualPts ( PointsToID  id) const
inline

Returns the points-to set which id represents. id must be stored in the cache.

Definition at line 106 of file PersistentPointsToCache.h.

107  {
108  // Check if the points-to set for ID has already been stored.
109  assert(idToPts.size() > id && "PPTC::getActualPts: points-to set not stored!");
110  return *idToPts.at(id);
111  }

◆ getAllPts()

template<typename Data >
Map<Data, unsigned> SVF::PersistentPointsToCache< Data >::getAllPts ( void  )
inline

Returns all points-to sets stored by this cache as keys to a map. Values are all 1. We use the map to be more compatible with getAllPts in the various PTDatas. Performance is a non-issue (for now) since this is just used for evaluation's sake.

Definition at line 345 of file PersistentPointsToCache.h.

346  {
347  Map<Data, unsigned> allPts;
348  for (const auto &d : idToPts) allPts[*d] = 1;
349  return allPts;
350  }

◆ initStats()

template<typename Data >
void SVF::PersistentPointsToCache< Data >::initStats ( void  )
inlineprivate

◆ intersectPts()

template<typename Data >
PointsToID SVF::PersistentPointsToCache< Data >::intersectPts ( PointsToID  lhs,
PointsToID  rhs 
)
inline

Intersects lhs and rhs (lhs AND rhs) and returns the intersection's ID.

Definition at line 236 of file PersistentPointsToCache.h.

237  {
238  static const DataOp intersectionOp = [](const Data &lhs, const Data &rhs)
239  {
240  return lhs & rhs;
241  };
242 
244 
245  // Order operands so we don't perform x U y and y U x separately.
246  std::pair<PointsToID, PointsToID> operands = std::minmax(lhs, rhs);
247 
248  // Property cases.
249  // EMPTY_SET & x
250  if (operands.first == emptyPointsToId())
251  {
253  return emptyPointsToId();
254  }
255 
256  // x & x
257  if (operands.first == operands.second)
258  {
260  return operands.first;
261  }
262 
263  bool opPerformed = false;
264  const PointsToID result = opPts(lhs, rhs, intersectionOp, intersectionCache, true, opPerformed);
265  if (opPerformed)
266  {
268 
269  // When the result is empty, we won't be adding anything of substance.
270  if (result != emptyPointsToId())
271  {
272  // We performed lhs AND rhs = result, so...
273  // result AND rhs = result,
274  if (result != rhs)
275  {
276  intersectionCache[std::minmax(result, rhs)] = result;
279  }
280 
281  // and result AND lhs = result,
282  if (result != lhs)
283  {
284  intersectionCache[std::minmax(result, lhs)] = result;
287  }
288 
289  // Also (thanks reviewer #2)
290  // result U lhs = result,
291  if (result != emptyPointsToId() && result != lhs)
292  {
293  unionCache[std::minmax(lhs, result)] = lhs;
295  ++totalUnions;
296  }
297 
298  // And result U rhs = rhs.
299  if (result != emptyPointsToId() && result != rhs)
300  {
301  unionCache[std::minmax(rhs, result)] = rhs;
303  ++totalUnions;
304  }
305  }
306  }
307  else ++lookupIntersections;
308 
309  return result;
310  }

◆ newPointsToId()

template<typename Data >
PointsToID SVF::PersistentPointsToCache< Data >::newPointsToId ( void  )
inlineprivate

Definition at line 355 of file PersistentPointsToCache.h.

356  {
357  // Make sure we don't overflow.
358  assert(idCounter != emptyPointsToId() && "PPTC::newPointsToId: PointsToIDs exhausted! Try a larger type.");
359  return idCounter++;
360  }

◆ opPts()

template<typename Data >
PointsToID SVF::PersistentPointsToCache< Data >::opPts ( PointsToID  lhs,
PointsToID  rhs,
const DataOp dataOp,
OpCache opCache,
bool  commutative,
bool &  opPerformed 
)
inlineprivate

Performs dataOp on lhs and rhs, checking the opCache first and updating it afterwards. commutative indicates whether the operation in question is commutative or not. opPerformed is set to true if the operation was not cached and thus performed, false otherwise.

Definition at line 365 of file PersistentPointsToCache.h.

367  {
368  std::pair<PointsToID, PointsToID> operands;
369  // If we're commutative, we want to always perform the same operation: x op y.
370  // Performing x op y sometimes and y op x other times is a waste of time.
371  if (commutative) operands = std::minmax(lhs, rhs);
372  else operands = std::make_pair(lhs, rhs);
373 
374  // Check if we have performed this operation
375  OpCache::const_iterator foundResult = opCache.find(operands);
376  if (foundResult != opCache.end()) return foundResult->second;
377 
378  opPerformed = true;
379 
380  const Data &lhsPts = getActualPts(lhs);
381  const Data &rhsPts = getActualPts(rhs);
382 
383  Data result = dataOp(lhsPts, rhsPts);
384 
385  PointsToID resultId;
386  // Intern points-to set: check if result already exists.
387  typename PTSToIDMap::const_iterator foundId = ptsToId.find(result);
388  if (foundId != ptsToId.end()) resultId = foundId->second;
389  else
390  {
391  resultId = newPointsToId();
392  idToPts.push_back(std::make_unique<Data>(result));
393  ptsToId[result] = resultId;
394  }
395 
396  // Cache the result, for hash-consing.
397  opCache[operands] = resultId;
398 
399  return resultId;
400  }
const Data & getActualPts(PointsToID id) const
Returns the points-to set which id represents. id must be stored in the cache.

◆ printStats()

template<typename Data >
void SVF::PersistentPointsToCache< Data >::printStats ( const std::string  subtitle) const
inline

Print statistics on operations and points-to set numbers.

Definition at line 313 of file PersistentPointsToCache.h.

314  {
315  static const unsigned fieldWidth = 25;
316  SVFUtil::outs().flags(std::ios::left);
317 
318  SVFUtil::outs() << std::setw(fieldWidth) << "UniquePointsToSets" << idToPts.size() << "\n";
319 
320  SVFUtil::outs() << std::setw(fieldWidth) << "TotalUnions" << totalUnions << "\n";
321  SVFUtil::outs() << std::setw(fieldWidth) << "PropertyUnions" << propertyUnions << "\n";
322  SVFUtil::outs() << std::setw(fieldWidth) << "UniqueUnions" << uniqueUnions << "\n";
323  SVFUtil::outs() << std::setw(fieldWidth) << "LookupUnions" << lookupUnions << "\n";
324  SVFUtil::outs() << std::setw(fieldWidth) << "PreemptiveUnions" << preemptiveUnions << "\n";
325 
326  SVFUtil::outs() << std::setw(fieldWidth) << "TotalComplements" << totalComplements << "\n";
327  SVFUtil::outs() << std::setw(fieldWidth) << "PropertyComplements" << propertyComplements << "\n";
328  SVFUtil::outs() << std::setw(fieldWidth) << "UniqueComplements" << uniqueComplements << "\n";
329  SVFUtil::outs() << std::setw(fieldWidth) << "LookupComplements" << lookupComplements << "\n";
330  SVFUtil::outs() << std::setw(fieldWidth) << "PreemptiveComplements" << preemptiveComplements << "\n";
331 
332  SVFUtil::outs() << std::setw(fieldWidth) << "TotalIntersections" << totalIntersections << "\n";
333  SVFUtil::outs() << std::setw(fieldWidth) << "PropertyIntersections" << propertyIntersections << "\n";
334  SVFUtil::outs() << std::setw(fieldWidth) << "UniqueIntersections" << uniqueIntersections << "\n";
335  SVFUtil::outs() << std::setw(fieldWidth) << "LookupIntersections" << lookupIntersections << "\n";
336  SVFUtil::outs() << std::setw(fieldWidth) << "PreemptiveIntersections" << preemptiveIntersections << "\n";
337 
338  SVFUtil::outs().flush();
339  }
std::ostream & outs()
Overwrite llvm::outs()
Definition: SVFUtil.h:50

◆ remapAllPts()

template<typename Data >
void SVF::PersistentPointsToCache< Data >::remapAllPts ( void  )
inline

Remaps all points-to sets stored in the cache to the current mapping.

Definition at line 80 of file PersistentPointsToCache.h.

81  {
82  for (auto &d : idToPts) d->checkAndRemap();
83 
84  // Rebuild ptsToId from idToPts.
85  ptsToId.clear();
86  for (PointsToID i = 0; i < idToPts.size(); ++i) ptsToId[*idToPts[i]] = i;
87  }

◆ reset()

template<typename Data >
void SVF::PersistentPointsToCache< Data >::reset ( void  )
inline

Resets the cache removing everything except the emptyData it was initialised with.

Definition at line 66 of file PersistentPointsToCache.h.

67  {
68  clear();
69 
70  // Put the empty data back in.
71  ptsToId[Data()] = emptyPointsToId();
72  idToPts.push_back(std::make_unique<Data>());
73 
74  idCounter = 1;
75  // Cache is empty...
76  initStats();
77  }

◆ unionPts()

template<typename Data >
PointsToID SVF::PersistentPointsToCache< Data >::unionPts ( PointsToID  lhs,
PointsToID  rhs 
)
inline

Unions lhs and rhs and returns their union's ID.

Definition at line 114 of file PersistentPointsToCache.h.

115  {
116  static const DataOp unionOp = [](const Data &lhs, const Data &rhs)
117  {
118  return lhs | rhs;
119  };
120 
121  ++totalUnions;
122 
123  // Order operands so we don't perform x U y and y U x separately.
124  std::pair<PointsToID, PointsToID> operands = std::minmax(lhs, rhs);
125 
126  // Property cases.
127  // EMPTY_SET U x
128  if (operands.first == emptyPointsToId())
129  {
130  ++propertyUnions;
131  return operands.second;
132  }
133 
134  // x U x
135  if (operands.first == operands.second)
136  {
137  ++propertyUnions;
138  return operands.first;
139  }
140 
141  bool opPerformed = false;
142  PointsToID result = opPts(lhs, rhs, unionOp, unionCache, true, opPerformed);
143 
144  if (opPerformed)
145  {
146  ++uniqueUnions;
147 
148  // We can use lhs/rhs here rather than our ordered operands,
149  // because the operation was commutative.
150 
151  // if x U y = z, then x U z = z,
152  if (lhs != result)
153  {
154  unionCache[std::minmax(lhs, result)] = result;
156  ++totalUnions;
157  }
158 
159  // and y U z = z.
160  if (rhs != result)
161  {
162  unionCache[std::minmax(rhs, result)] = result;
164  ++totalUnions;
165  }
166  }
167  else ++lookupUnions;
168 
169  return result;
170  }

Member Data Documentation

◆ complementCache

template<typename Data >
OpCache SVF::PersistentPointsToCache< Data >::complementCache
private

Maps two IDs to their relative complement.

Definition at line 436 of file PersistentPointsToCache.h.

◆ idCounter

template<typename Data >
PointsToID SVF::PersistentPointsToCache< Data >::idCounter
private

Used to generate new PointsToIDs. Any non-zero is valid.

Definition at line 441 of file PersistentPointsToCache.h.

◆ idToPts

template<typename Data >
std::vector<std::unique_ptr<Data> > SVF::PersistentPointsToCache< Data >::idToPts
private

Maps points-to IDs (indices) to their corresponding points-to set. Reverse of idToPts. Elements are only added through push_back, so the number of elements stored is the size of the vector. Not const so we can remap.

Definition at line 429 of file PersistentPointsToCache.h.

◆ intersectionCache

template<typename Data >
OpCache SVF::PersistentPointsToCache< Data >::intersectionCache
private

Maps two IDs to their intersection. Keys must be sorted.

Definition at line 438 of file PersistentPointsToCache.h.

◆ lookupComplements

template<typename Data >
u64_t SVF::PersistentPointsToCache< Data >::lookupComplements
private

Definition at line 452 of file PersistentPointsToCache.h.

◆ lookupIntersections

template<typename Data >
u64_t SVF::PersistentPointsToCache< Data >::lookupIntersections
private

Definition at line 457 of file PersistentPointsToCache.h.

◆ lookupUnions

template<typename Data >
u64_t SVF::PersistentPointsToCache< Data >::lookupUnions
private

Definition at line 447 of file PersistentPointsToCache.h.

◆ preemptiveComplements

template<typename Data >
u64_t SVF::PersistentPointsToCache< Data >::preemptiveComplements
private

Definition at line 453 of file PersistentPointsToCache.h.

◆ preemptiveIntersections

template<typename Data >
u64_t SVF::PersistentPointsToCache< Data >::preemptiveIntersections
private

Definition at line 458 of file PersistentPointsToCache.h.

◆ preemptiveUnions

template<typename Data >
u64_t SVF::PersistentPointsToCache< Data >::preemptiveUnions
private

Definition at line 448 of file PersistentPointsToCache.h.

◆ propertyComplements

template<typename Data >
u64_t SVF::PersistentPointsToCache< Data >::propertyComplements
private

Definition at line 451 of file PersistentPointsToCache.h.

◆ propertyIntersections

template<typename Data >
u64_t SVF::PersistentPointsToCache< Data >::propertyIntersections
private

Definition at line 456 of file PersistentPointsToCache.h.

◆ propertyUnions

template<typename Data >
u64_t SVF::PersistentPointsToCache< Data >::propertyUnions
private

Definition at line 446 of file PersistentPointsToCache.h.

◆ ptsToId

template<typename Data >
PTSToIDMap SVF::PersistentPointsToCache< Data >::ptsToId
private

Maps points-to sets to their corresponding ID.

Definition at line 431 of file PersistentPointsToCache.h.

◆ totalComplements

template<typename Data >
u64_t SVF::PersistentPointsToCache< Data >::totalComplements
private

Definition at line 449 of file PersistentPointsToCache.h.

◆ totalIntersections

template<typename Data >
u64_t SVF::PersistentPointsToCache< Data >::totalIntersections
private

Definition at line 454 of file PersistentPointsToCache.h.

◆ totalUnions

template<typename Data >
u64_t SVF::PersistentPointsToCache< Data >::totalUnions
private

Definition at line 444 of file PersistentPointsToCache.h.

◆ unionCache

template<typename Data >
OpCache SVF::PersistentPointsToCache< Data >::unionCache
private

Maps two IDs to their union. Keys must be sorted.

Definition at line 434 of file PersistentPointsToCache.h.

◆ uniqueComplements

template<typename Data >
u64_t SVF::PersistentPointsToCache< Data >::uniqueComplements
private

Definition at line 450 of file PersistentPointsToCache.h.

◆ uniqueIntersections

template<typename Data >
u64_t SVF::PersistentPointsToCache< Data >::uniqueIntersections
private

Definition at line 455 of file PersistentPointsToCache.h.

◆ uniqueUnions

template<typename Data >
u64_t SVF::PersistentPointsToCache< Data >::uniqueUnions
private

Definition at line 445 of file PersistentPointsToCache.h.


The documentation for this class was generated from the following file: