LLVM 24.0.0git
ImmutableMap.h
Go to the documentation of this file.
1//===--- ImmutableMap.h - Immutable (functional) map interface --*- C++ -*-===//
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/// \file
10/// This file defines the ImmutableMap class.
11///
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_ADT_IMMUTABLEMAP_H
15#define LLVM_ADT_IMMUTABLEMAP_H
16
17#include "llvm/ADT/FoldingSet.h"
20#include <utility>
21
22namespace llvm {
23
24/// Traits class used by ImmutableMap. While both the first and second elements
25/// in a pair are used to generate profile information, only the first element
26/// (the key) is used by isEqual and isLess.
27template <typename T, typename S>
29 using value_type = const std::pair<T,S>;
30 using value_type_ref = const value_type&;
31 using key_type = const T;
32 using key_type_ref = const T&;
33 using data_type = const S;
34 using data_type_ref = const S&;
35
37 return V.first;
38 }
39
41 return V.second;
42 }
43
44 static inline bool isEqual(key_type_ref L, key_type_ref R) {
46 }
47 static inline bool isLess(key_type_ref L, key_type_ref R) {
49 }
50
51 static inline bool isDataEqual(data_type_ref L, data_type_ref R) {
53 }
54
59};
60
61template <typename KeyT, typename ValT,
62 typename ValInfo = ImutKeyValueInfo<KeyT, ValT>,
63 bool Canonicalize = true>
65public:
66 using value_type = typename ValInfo::value_type;
67 using value_type_ref = typename ValInfo::value_type_ref;
68 using key_type = typename ValInfo::key_type;
69 using key_type_ref = typename ValInfo::key_type_ref;
70 using data_type = typename ValInfo::data_type;
71 using data_type_ref = typename ValInfo::data_type_ref;
73
74protected:
76
77public:
78 /// Constructs a map from a pointer to a tree root. In general one
79 /// should use a Factory object to create maps instead of directly
80 /// invoking the constructor, but there are cases where make this
81 /// constructor public is useful.
82 explicit ImmutableMap(const TreeTy *R) : Root(const_cast<TreeTy *>(R)) {}
83
84 class Factory {
85 typename TreeTy::Factory F;
86
87 public:
88 Factory() = default;
89
91
92 Factory(const Factory &) = delete;
93 Factory &operator=(const Factory &) = delete;
94
95 ImmutableMap getEmptyMap() { return ImmutableMap(F.getEmptyTree()); }
96
99 TreeTy *T = F.add(Old.Root.get(), std::pair<key_type, data_type>(K, D));
100 if constexpr (Canonicalize)
101 return ImmutableMap(F.getCanonicalTree(T));
102 else
103 return ImmutableMap(T);
104 }
105
107 TreeTy *T = F.remove(Old.Root.get(), K);
108 if constexpr (Canonicalize)
109 return ImmutableMap(F.getCanonicalTree(T));
110 else
111 return ImmutableMap(T);
112 }
113
114 typename TreeTy::Factory *getTreeFactory() const {
115 return const_cast<typename TreeTy::Factory *>(&F);
116 }
117 };
118
119 [[nodiscard]] bool contains(key_type_ref K) const {
120 return Root ? Root->contains(K) : false;
121 }
122
123 /// Compares two maps for equality. For a canonicalizing factory, maps with
124 /// equal contents share the same tree, so this is an O(1) pointer comparison
125 /// (like ImmutableList); only maps created by the same factory may be
126 /// compared. Otherwise it is a structural comparison.
127 [[nodiscard]] bool operator==(const ImmutableMap &RHS) const {
128 if constexpr (Canonicalize)
129 return Root == RHS.Root;
130 else
131 return Root && RHS.Root ? Root->isEqual(*RHS.Root.get())
132 : Root == RHS.Root;
133 }
134
135 [[nodiscard]] bool operator!=(const ImmutableMap &RHS) const {
136 if constexpr (Canonicalize)
137 return Root != RHS.Root;
138 else
139 return Root && RHS.Root ? Root->isNotEqual(*RHS.Root.get())
140 : Root != RHS.Root;
141 }
142
143 [[nodiscard]] TreeTy *getRoot() const {
144 if (Root) { Root->retain(); }
145 return Root.get();
146 }
147
148 [[nodiscard]] TreeTy *getRootWithoutRetain() const { return Root.get(); }
149
151 if (Root) Root->retain();
152 }
153
155 if (Root) Root->release();
156 }
157
158 [[nodiscard]] bool isEmpty() const { return !Root; }
159
160public:
161 //===--------------------------------------------------===//
162 // For testing.
163 //===--------------------------------------------------===//
164
165 void verify() const { if (Root) Root->verify(); }
166
167 //===--------------------------------------------------===//
168 // Iterators.
169 //===--------------------------------------------------===//
170
171 class iterator : public ImutAVLValueIterator<ImmutableMap> {
172 friend class ImmutableMap;
173
174 iterator() = default;
175 explicit iterator(TreeTy *Tree) : iterator::ImutAVLValueIterator(Tree) {}
176
177 public:
178 key_type_ref getKey() const { return (*this)->first; }
179 data_type_ref getData() const { return (*this)->second; }
180 };
181
182 [[nodiscard]] iterator begin() const { return iterator(Root.get()); }
183 [[nodiscard]] iterator end() const { return iterator(); }
184
185 [[nodiscard]] data_type *lookup(key_type_ref K) const {
186 if (Root) {
187 TreeTy* T = Root->find(K);
188 if (T) return &T->getValue().second;
189 }
190
191 return nullptr;
192 }
193
194 /// Returns the <key,value> pair in the ImmutableMap for which key is the
195 /// highest in the ordering of keys in the map. This method returns NULL if
196 /// the map is empty.
197 [[nodiscard]] value_type *getMaxElement() const {
198 return Root ? &(Root->getMaxElement()->getValue()) : nullptr;
199 }
200
201 //===--------------------------------------------------===//
202 // Utility methods.
203 //===--------------------------------------------------===//
204
205 [[nodiscard]] unsigned getHeight() const {
206 return Root ? Root->getHeight() : 0;
207 }
208
209 static inline void Profile(FoldingSetNodeID& ID, const ImmutableMap& M) {
210 ID.AddPointer(M.Root.get());
211 }
212
213 inline void Profile(FoldingSetNodeID& ID) const {
214 return Profile(ID,*this);
215 }
216};
217
218// NOTE: This will possibly become the new implementation of ImmutableMap some day.
219template <typename KeyT, typename ValT,
220typename ValInfo = ImutKeyValueInfo<KeyT,ValT>>
222public:
223 using value_type = typename ValInfo::value_type;
224 using value_type_ref = typename ValInfo::value_type_ref;
225 using key_type = typename ValInfo::key_type;
226 using key_type_ref = typename ValInfo::key_type_ref;
227 using data_type = typename ValInfo::data_type;
228 using data_type_ref = typename ValInfo::data_type_ref;
230 using FactoryTy = typename TreeTy::Factory;
231
232protected:
235
236public:
237 /// Constructs a map from a pointer to a tree root. In general one
238 /// should use a Factory object to create maps instead of directly
239 /// invoking the constructor, but there are cases where make this
240 /// constructor public is useful.
242 : Root(const_cast<TreeTy *>(R)), Factory(F) {}
243
246 : Root(X.getRootWithoutRetain()), Factory(F.getTreeFactory()) {}
247
249 return ImmutableMapRef(nullptr, F);
250 }
251
253 if (Root) Root->retain();
254 }
255
257 if (Root) Root->release();
258 }
259
261 TreeTy *NewT =
262 Factory->add(Root.get(), std::pair<key_type, data_type>(K, D));
263 return ImmutableMapRef(NewT, Factory);
264 }
265
267 TreeTy *NewT = Factory->remove(Root.get(), K);
268 return ImmutableMapRef(NewT, Factory);
269 }
270
271 [[nodiscard]] bool contains(key_type_ref K) const {
272 return Root ? Root->contains(K) : false;
273 }
274
276 return ImmutableMap<KeyT, ValT>(Factory->getCanonicalTree(Root.get()));
277 }
278
279 [[nodiscard]] bool operator==(const ImmutableMapRef &RHS) const {
280 return Root && RHS.Root ? Root->isEqual(*RHS.Root.get()) : Root == RHS.Root;
281 }
282
283 [[nodiscard]] bool operator!=(const ImmutableMapRef &RHS) const {
284 return Root && RHS.Root ? Root->isNotEqual(*RHS.Root.get())
285 : Root != RHS.Root;
286 }
287
288 [[nodiscard]] bool isEmpty() const { return !Root; }
289
290 //===--------------------------------------------------===//
291 // For testing.
292 //===--------------------------------------------------===//
293
294 void verify() const {
295 if (Root)
296 Root->verify();
297 }
298
299 //===--------------------------------------------------===//
300 // Iterators.
301 //===--------------------------------------------------===//
302
303 class iterator : public ImutAVLValueIterator<ImmutableMapRef> {
304 friend class ImmutableMapRef;
305
306 iterator() = default;
307 explicit iterator(TreeTy *Tree) : iterator::ImutAVLValueIterator(Tree) {}
308
309 public:
310 key_type_ref getKey() const { return (*this)->first; }
311 data_type_ref getData() const { return (*this)->second; }
312 };
313
314 [[nodiscard]] iterator begin() const { return iterator(Root.get()); }
315 [[nodiscard]] iterator end() const { return iterator(); }
316
317 [[nodiscard]] data_type *lookup(key_type_ref K) const {
318 if (Root) {
319 TreeTy* T = Root->find(K);
320 if (T) return &T->getValue().second;
321 }
322
323 return nullptr;
324 }
325
326 /// Returns the <key,value> pair in the ImmutableMap for which key is the
327 /// highest in the ordering of keys in the map. This method returns NULL if
328 /// the map is empty.
329 [[nodiscard]] value_type *getMaxElement() const {
330 return Root ? &(Root->getMaxElement()->getValue()) : nullptr;
331 }
332
333 //===--------------------------------------------------===//
334 // Utility methods.
335 //===--------------------------------------------------===//
336
337 [[nodiscard]] unsigned getHeight() const {
338 return Root ? Root->getHeight() : 0;
339 }
340
341 static inline void Profile(FoldingSetNodeID &ID, const ImmutableMapRef &M) {
342 ID.AddPointer(M.Root.get());
343 }
344
345 inline void Profile(FoldingSetNodeID &ID) const { return Profile(ID, *this); }
346};
347
348} // end namespace llvm
349
350#endif // LLVM_ADT_IMMUTABLEMAP_H
This file defines the BumpPtrAllocator interface.
#define X(NUM, ENUM, NAME)
Definition ELF.h:856
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
This file defines a hash set that can be used to remove duplication of nodes in a graph.
This file defines the ImutAVLTree and ImmutableSet classes.
static constexpr Value * getValue(Ty &ValueOrUse)
#define F(x, y, z)
Definition MD5.cpp:54
Load MIR Sample Profile
#define T
Value * RHS
This class is used to gather all the unique data bits of a node.
Definition FoldingSet.h:208
key_type_ref getKey() const
data_type_ref getData() const
unsigned getHeight() const
ImmutableMap< KeyT, ValT > asImmutableMap() const
static ImmutableMapRef getEmptyMap(FactoryTy *F)
void Profile(FoldingSetNodeID &ID) const
bool operator!=(const ImmutableMapRef &RHS) const
bool contains(key_type_ref K) const
static void Profile(FoldingSetNodeID &ID, const ImmutableMapRef &M)
typename ValInfo::data_type data_type
typename ValInfo::data_type_ref data_type_ref
typename ValInfo::key_type key_type
IntrusiveRefCntPtr< TreeTy > Root
ImutAVLTree< ValInfo > TreeTy
typename ValInfo::value_type_ref value_type_ref
bool operator==(const ImmutableMapRef &RHS) const
ImmutableMapRef remove(key_type_ref K) const
typename ValInfo::key_type_ref key_type_ref
value_type * getMaxElement() const
Returns the <key,value> pair in the ImmutableMap for which key is the highest in the ordering of keys...
ImmutableMapRef add(key_type_ref K, data_type_ref D) const
typename ValInfo::value_type value_type
iterator begin() const
ImmutableMapRef(const TreeTy *R, FactoryTy *F)
Constructs a map from a pointer to a tree root.
data_type * lookup(key_type_ref K) const
iterator end() const
ImmutableMapRef(const ImmutableMap< KeyT, ValT > &X, typename ImmutableMap< KeyT, ValT >::Factory &F)
typename TreeTy::Factory FactoryTy
TreeTy::Factory * getTreeFactory() const
ImmutableMap remove(ImmutableMap Old, key_type_ref K)
Factory(BumpPtrAllocator &Alloc)
Factory & operator=(const Factory &)=delete
ImmutableMap add(ImmutableMap Old, key_type_ref K, data_type_ref D)
Factory(const Factory &)=delete
key_type_ref getKey() const
data_type_ref getData() const
typename ValInfo::data_type_ref data_type_ref
TreeTy * getRootWithoutRetain() const
bool isEmpty() const
iterator begin() const
typename ValInfo::key_type_ref key_type_ref
TreeTy * getRoot() const
typename ValInfo::value_type_ref value_type_ref
iterator end() const
value_type * getMaxElement() const
Returns the <key,value> pair in the ImmutableMap for which key is the highest in the ordering of keys...
void verify() const
typename ValInfo::key_type key_type
typename ValInfo::value_type value_type
typename ValInfo::data_type data_type
void Profile(FoldingSetNodeID &ID) const
bool operator!=(const ImmutableMap &RHS) const
ImmutableMap(const TreeTy *R)
Constructs a map from a pointer to a tree root.
bool contains(key_type_ref K) const
unsigned getHeight() const
data_type * lookup(key_type_ref K) const
IntrusiveRefCntPtr< TreeTy > Root
bool operator==(const ImmutableMap &RHS) const
Compares two maps for equality.
ImutAVLTree< ValInfo, Canonicalize > TreeTy
static void Profile(FoldingSetNodeID &ID, const ImmutableMap &M)
ImutAVLFactory< ValInfo, Canonicalize > Factory
A smart pointer to a reference-counted object that inherits from RefCountedBase or ThreadSafeRefCount...
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
This is an optimization pass for GlobalISel generic memory operations.
BumpPtrAllocatorImpl<> BumpPtrAllocator
The standard BumpPtrAllocator which just uses the default template parameters.
Definition Allocator.h:390
static bool isLess(key_type_ref LHS, key_type_ref RHS)
static bool isEqual(key_type_ref LHS, key_type_ref RHS)
Traits class used by ImmutableMap.
const value_type & value_type_ref
static void Profile(FoldingSetNodeID &ID, value_type_ref V)
static bool isLess(key_type_ref L, key_type_ref R)
static key_type_ref KeyOfValue(value_type_ref V)
const std::pair< T, S > value_type
static data_type_ref DataOfValue(value_type_ref V)
static bool isDataEqual(data_type_ref L, data_type_ref R)
static bool isEqual(key_type_ref L, key_type_ref R)
static void Profile(FoldingSetNodeID &ID, value_type_ref X)