CIRCT 20.0.0git
Loading...
Searching...
No Matches
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
20using namespace circt;
21using 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
78void 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}
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
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.
DenseMap< Key, FieldRef > refs
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.