LLVM 24.0.0git
SortedVectorMap.h
Go to the documentation of this file.
1//===- llvm/ADT/SortedVectorMap.h - Map backed by SmallVector *- 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 implements a map backed by a sorted SmallVector. It provides a
11/// std::map-like interface with binary search lookup while maintaining
12/// contiguous memory layout and dense cache locality.
13///
14/// SortedVectorMap is intended for:
15/// - Small maps where memory footprint is a primary concern. In particular, it
16/// avoids the initial bucket overhead of DenseMap (e.g. 64 buckets by
17/// default) when only a few elements are stored.
18/// - Use cases that require iteration in sorted key order.
19///
20/// Trade-offs:
21/// - Lookups take O(log N) time via binary search rather than O(1) in DenseMap.
22/// - Insertions and deletions take O(N) time due to shifting elements in the
23/// underlying vector, making it best suited for small N or mostly-read data.
24/// - Compared to std::map, elements are stored contiguously, eliminating
25/// per-node heap allocations and pointer chasing.
26/// - Compared to MapVector, elements are ordered by key rather than insertion
27/// order, with zero auxiliary hash table overhead.
28///
29//===----------------------------------------------------------------------===//
30
31#ifndef LLVM_ADT_SORTEDVECTORMAP_H
32#define LLVM_ADT_SORTEDVECTORMAP_H
33
34#include "llvm/ADT/STLExtras.h"
37#include <functional>
38#include <tuple>
39#include <utility>
40
41namespace llvm {
42
43/// A map implementation backed by a sorted SmallVector.
44/// Key-value pairs are stored in contiguous memory ordered by \p KeyCompare.
45template <typename KeyT, typename ValueT, unsigned N = 0,
46 typename KeyCompare = std::less<KeyT>>
48public:
49 using key_type = KeyT;
50 using mapped_type = ValueT;
51 using value_type = std::pair<KeyT, ValueT>;
54
59
60private:
61 VectorType Vector;
62 LLVM_NO_UNIQUE_ADDRESS KeyCompare Comp;
63
64 template <typename K1, typename K2>
65 bool is_equal(const K1 &A, const K2 &B) const {
66 return !Comp(A, B) && !Comp(B, A);
67 }
68
69 template <typename K> const_iterator lower_bound(const K &Key) const {
71 [this](const value_type &E, const K &KeyVal) {
72 return Comp(E.first, KeyVal);
73 });
74 }
75
76 template <typename K>
77 std::pair<const_iterator, bool> find_or_insert_location(const K &Key) const {
78 if (!Vector.empty() && Comp(Vector.back().first, Key))
79 return {Vector.end(), false};
80 auto It = lower_bound(Key);
81 bool Found = (It != Vector.end() && is_equal(Key, It->first));
82 return {It, Found};
83 }
84
85 template <typename K>
86 std::pair<iterator, bool> find_or_insert_location(const K &Key) {
87 auto [ConstIt, Found] = std::as_const(*this).find_or_insert_location(Key);
88 return {Vector.begin() + (ConstIt - Vector.begin()), Found};
89 }
90
91 template <typename KeyArgT, typename... Ts>
92 std::pair<iterator, bool> try_emplace_impl(KeyArgT &&Key, Ts &&...Args) {
93 auto [It, Found] = find_or_insert_location(Key);
94 if (Found)
95 return {It, false};
96 It = Vector.insert(
97 It, value_type(std::piecewise_construct,
98 std::forward_as_tuple(std::forward<KeyArgT>(Key)),
99 std::forward_as_tuple(std::forward<Ts>(Args)...)));
100 return {It, true};
101 }
102
103public:
104 SortedVectorMap() = default;
105
106 // Iterators
107 iterator begin() { return Vector.begin(); }
108 iterator end() { return Vector.end(); }
109 const_iterator begin() const { return Vector.begin(); }
110 const_iterator end() const { return Vector.end(); }
111 const_iterator cbegin() const { return Vector.begin(); }
112 const_iterator cend() const { return Vector.end(); }
113
114 reverse_iterator rbegin() { return Vector.rbegin(); }
115 reverse_iterator rend() { return Vector.rend(); }
116 const_reverse_iterator rbegin() const { return Vector.rbegin(); }
117 const_reverse_iterator rend() const { return Vector.rend(); }
118 const_reverse_iterator crbegin() const { return Vector.rbegin(); }
119 const_reverse_iterator crend() const { return Vector.rend(); }
120
121 // Capacity
122 [[nodiscard]] bool empty() const { return Vector.empty(); }
123 size_type size() const { return Vector.size(); }
124 size_type capacity() const { return Vector.capacity(); }
125 void reserve(size_type Cap) { Vector.reserve(Cap); }
126
127 // Element Access & Lookups
128
129 template <typename K> const_iterator find(const K &Key) const {
130 auto [It, Found] = find_or_insert_location(Key);
131 return Found ? It : Vector.end();
132 }
133
134 template <typename K> iterator find(const K &Key) {
135 auto [It, Found] = find_or_insert_location(Key);
136 return Found ? It : Vector.end();
137 }
138
139 template <typename... Ts>
140 std::pair<iterator, bool> try_emplace(const KeyT &Key, Ts &&...Args) {
141 return try_emplace_impl(Key, std::forward<Ts>(Args)...);
142 }
143
144 template <typename... Ts>
145 std::pair<iterator, bool> try_emplace(KeyT &&Key, Ts &&...Args) {
146 return try_emplace_impl(std::move(Key), std::forward<Ts>(Args)...);
147 }
148
149 std::pair<iterator, bool> insert(const value_type &KV) {
150 return try_emplace_impl(KV.first, KV.second);
151 }
152
153 std::pair<iterator, bool> insert(value_type &&KV) {
154 return try_emplace_impl(std::move(KV.first), std::move(KV.second));
155 }
156
157 ValueT &operator[](const KeyT &Key) {
158 return try_emplace_impl(Key).first->second;
159 }
160
161 ValueT &operator[](KeyT &&Key) {
162 return try_emplace_impl(std::move(Key)).first->second;
163 }
164
165 iterator erase(iterator Pos) { return Vector.erase(Pos); }
166 iterator erase(const_iterator Pos) { return Vector.erase(Pos); }
167
168 bool operator==(const SortedVectorMap &Other) const {
169 return Vector == Other.Vector;
170 }
171};
172} // namespace llvm
173
174#endif // LLVM_ADT_SORTEDVECTORMAP_H
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define LLVM_NO_UNIQUE_ADDRESS
Definition Compiler.h:481
This file contains some templates that are useful if you are working with the STL at all.
This file defines the SmallVector class.
typename SuperClass::const_iterator const_iterator
typename SuperClass::iterator iterator
typename SuperClass::size_type size_type
std::reverse_iterator< const_iterator > const_reverse_iterator
std::reverse_iterator< iterator > reverse_iterator
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
const_iterator find(const K &Key) const
reverse_iterator rbegin()
typename VectorType::iterator iterator
size_type capacity() const
void reserve(size_type Cap)
const_reverse_iterator crbegin() const
typename VectorType::const_iterator const_iterator
ValueT & operator[](const KeyT &Key)
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
typename VectorType::const_reverse_iterator const_reverse_iterator
ValueT & operator[](KeyT &&Key)
const_reverse_iterator rend() const
std::pair< iterator, bool > try_emplace(const KeyT &Key, Ts &&...Args)
reverse_iterator rend()
size_type size() const
std::pair< KeyT, ValueT > value_type
const_iterator cend() const
const_reverse_iterator rbegin() const
const_iterator begin() const
const_iterator cbegin() const
iterator find(const K &Key)
SmallVector< value_type, N > VectorType
iterator erase(const_iterator Pos)
const_reverse_iterator crend() const
typename VectorType::size_type size_type
std::pair< iterator, bool > insert(const value_type &KV)
typename VectorType::reverse_iterator reverse_iterator
bool operator==(const SortedVectorMap &Other) const
std::pair< iterator, bool > insert(value_type &&KV)
iterator erase(iterator Pos)
const_iterator end() const
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
@ Other
Any other memory.
Definition ModRef.h:68
auto lower_bound(R &&Range, T &&Value)
Provide wrappers to std::lower_bound which take ranges instead of having to pass begin/end explicitly...
Definition STLExtras.h:2052
#define N