@@ -60,6 +60,29 @@ class ParentMapContext::ParentMap {
60
60
61
61
template <typename , typename ...> friend struct ::MatchParents;
62
62
63
+ template <class T > struct IndirectDenseMapInfo {
64
+ using Ptr = T *;
65
+ using Base = llvm::DenseMapInfo<std::remove_cv_t <T>>;
66
+ static inline Ptr getEmptyKey () {
67
+ return static_cast <Ptr >(llvm::DenseMapInfo<void *>::getEmptyKey ());
68
+ }
69
+ static inline Ptr getTombstoneKey () {
70
+ return static_cast <Ptr >(llvm::DenseMapInfo<void *>::getTombstoneKey ());
71
+ }
72
+ static unsigned getHashValue (Ptr Val) {
73
+ return Val == getEmptyKey () || Val == getTombstoneKey ()
74
+ ? 0
75
+ : Base::getHashValue (*Val);
76
+ }
77
+ static bool isEqual (Ptr LHS, Ptr RHS) {
78
+ if (LHS == getEmptyKey () || LHS == getTombstoneKey () ||
79
+ RHS == getEmptyKey () || RHS == getTombstoneKey ()) {
80
+ return LHS == RHS;
81
+ }
82
+ return Base::isEqual (*LHS, *RHS);
83
+ }
84
+ };
85
+
63
86
// / Contains parents of a node.
64
87
class ParentVector {
65
88
public:
@@ -70,16 +93,38 @@ class ParentMapContext::ParentMap {
70
93
push_back (Value);
71
94
}
72
95
bool contains (const DynTypedNode &Value) {
73
- return Seen.contains (Value);
96
+ assert (Value.getMemoizationData ());
97
+ bool found = FragileLazySeenCache.contains (&Value);
98
+ while (!found && ItemsProcessed < Items.size ()) {
99
+ found |= FragileLazySeenCache.insert (&Items[ItemsProcessed]).second ;
100
+ ++ItemsProcessed;
101
+ }
102
+ return found;
74
103
}
75
104
void push_back (const DynTypedNode &Value) {
76
- if (!Value.getMemoizationData () || Seen.insert (Value).second )
105
+ if (!Value.getMemoizationData () || !contains (Value)) {
106
+ const size_t OldCapacity = Items.capacity ();
77
107
Items.push_back (Value);
108
+ if (OldCapacity != Items.capacity ()) {
109
+ // Pointers are invalidated; remove them.
110
+ ItemsProcessed = 0 ;
111
+ // Free memory to avoid doubling peak memory usage during rehashing
112
+ FragileLazySeenCache.clear ();
113
+ }
114
+ }
78
115
}
79
116
llvm::ArrayRef<DynTypedNode> view () const { return Items; }
80
117
private:
118
+ // BE CAREFUL. Pointers into this container are stored in the
119
+ // `FragileLazySeenCache` set below.
81
120
llvm::SmallVector<DynTypedNode, 2 > Items;
82
- llvm::SmallDenseSet<DynTypedNode, 2 > Seen;
121
+ // This cache is fragile because it contains pointers that are invalidated
122
+ // when the vector capacity changes.
123
+ llvm::SmallDenseSet<const DynTypedNode *, 2 ,
124
+ IndirectDenseMapInfo<const DynTypedNode>>
125
+ FragileLazySeenCache;
126
+ // Lazily tracks which items have been processed for the cache.
127
+ size_t ItemsProcessed = 0 ;
83
128
};
84
129
85
130
// / Maps from a node to its parents. This is used for nodes that have
0 commit comments