CIRCT  20.0.0git
FieldRefCache.cpp
Go to the documentation of this file.
1 //===- FieldRefCache.cpp - FieldRef cache ---------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines FieldRefCache, a caching getFieldRefFromValue that caching
10 // FieldRef's for each queried value and all indexing operations visited during
11 // the walk.
12 //
13 //===----------------------------------------------------------------------===//
14 
17 #include "llvm/ADT/STLExtras.h"
18 #include "llvm/Support/FormatVariadic.h"
19 
20 using namespace circt;
21 using namespace firrtl;
22 
24  bool lookThroughCasts) {
25  // Vector of values and delta to next entry, as FieldRef's.
26  // Last will be root (delta == 0), so walking backwards constructs
27  // FieldRef's relative to root for all visited operations.
28  SmallVector<FieldRef> indexing;
29  // Ignore null value for simplicity.
30  if (!value)
31  return FieldRef();
32 
33 #ifndef NDEBUG
34  ++queries;
35 #endif
36 
37  while (value) {
38  // Check cache to see if already visited.
39  auto it = refs.find(Key(value, lookThroughCasts));
40  if (it != refs.end()) {
41  // Found! If entire query is hit, we're done.
42 #ifndef NDEBUG
43  ++hits;
44 #endif
45  auto ref = it->second;
46  if (indexing.empty())
47  return ref;
48  // Otherwise, add entry for this using cached FieldRef,
49  // and add the FieldRef's value as last (root) entry.
50  indexing.emplace_back(value, ref.getFieldID());
51  indexing.emplace_back(ref.getValue(), 0);
52  break;
53  }
54 #ifndef NDEBUG
55  ++computed;
56 #endif
57 
58  auto deltaRef = getDeltaRef(value, lookThroughCasts);
59  indexing.emplace_back(value, deltaRef.getFieldID());
60  value = deltaRef.getValue();
61  }
62  // Last entry in indexing is the root.
63  assert(!indexing.empty());
64  assert(indexing.back().getFieldID() == 0);
65 
66  auto root = indexing.back().getValue();
67  size_t id = 0;
68  FieldRef cur(root, 0);
69  for (auto &info : llvm::reverse(indexing)) {
70  id += info.getFieldID();
71  cur = FieldRef(root, id);
72  refs.try_emplace({info.getValue(), lookThroughCasts}, cur);
73  }
74  return cur;
75 }
76 
77 #ifndef NDEBUG
78 void firrtl::FieldRefCache::printStats(llvm::raw_ostream &os) const {
79  os << llvm::formatv("FieldRefCache stats:\n"
80  "\thits: {0}\n"
81  "\tcomputed: {1}\n"
82  "\tqueries: {2}\n",
83  hits, computed, queries);
84 }
85 void firrtl::FieldRefCache::addToTotals(size_t &totalHits,
86  size_t &totalComputed,
87  size_t &totalQueries) const {
88  totalHits += hits;
89  totalComputed += computed;
90  totalQueries += queries;
91 }
92 
94  // (Guarding under EXPENSIVE_CHECKS may be appropriate.)
95  for (auto &[key, ref] : refs)
96  assert(ref == firrtl::getFieldRefFromValue(key.getPointer(), key.getInt()));
97 }
98 #endif // NDEBUG
assert(baseType &&"element must be base type")
This class represents a reference to a specific field or element of an aggregate value.
Definition: FieldRef.h:28
llvm::PointerIntPair< Value, 1, bool > Key
Definition: FieldRefCache.h:27
void addToTotals(size_t &totalHits, size_t &totalComputed, size_t &totalQueries) const
void printStats(llvm::raw_ostream &os) const
FieldRef getFieldRefFromValue(Value value, bool lookThroughCasts=false)
Caching version of getFieldRefFromValue.
FieldRef getDeltaRef(Value value, bool lookThroughCasts=false)
Get the delta indexing from a value, as a FieldRef.
FieldRef getFieldRefFromValue(Value value, bool lookThroughCasts=false)
Get the FieldRef from a value.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
Definition: DebugAnalysis.h:21