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
57
58private:
59 VectorType Vector;
60 LLVM_NO_UNIQUE_ADDRESS KeyCompare Comp;
61
62 template <typename K1, typename K2>
63 bool is_equal(const K1 &A, const K2 &B) const {
64 return !Comp(A, B) && !Comp(B, A);
65 }
66
67 template <typename K> const_iterator lower_bound(const K &Key) const {
69 [this](const value_type &E, const K &KeyVal) {
70 return Comp(E.first, KeyVal);
71 });
72 }
73
74 template <typename K>
75 std::pair<const_iterator, bool> find_or_insert_location(const K &Key) const {
76 if (!Vector.empty() && Comp(Vector.back().first, Key))
77 return {Vector.end(), false};
78 auto It = lower_bound(Key);
79 bool Found = (It != Vector.end() && is_equal(Key, It->first));
80 return {It, Found};
81 }
82
83 template <typename K>
84 std::pair<iterator, bool> find_or_insert_location(const K &Key) {
85 auto [ConstIt, Found] = std::as_const(*this).find_or_insert_location(Key);
86 return {Vector.begin() + (ConstIt - Vector.begin()), Found};
87 }
88
89 template <typename KeyArgT, typename... Ts>
90 std::pair<iterator, bool> try_emplace_impl(KeyArgT &&Key, Ts &&...Args) {
91 auto [It, Found] = find_or_insert_location(Key);
92 if (Found)
93 return {It, false};
94 It = Vector.insert(
95 It, value_type(std::piecewise_construct,
96 std::forward_as_tuple(std::forward<KeyArgT>(Key)),
97 std::forward_as_tuple(std::forward<Ts>(Args)...)));
98 return {It, true};
99 }
100
101public:
102 SortedVectorMap() = default;
103
104 // Iterators
105 iterator begin() { return Vector.begin(); }
106 iterator end() { return Vector.end(); }
107 const_iterator begin() const { return Vector.begin(); }
108 const_iterator end() const { return Vector.end(); }
109
110 // Capacity
111 [[nodiscard]] bool empty() const { return Vector.empty(); }
112 size_type size() const { return Vector.size(); }
113 size_type capacity() const { return Vector.capacity(); }
114 void reserve(size_type Cap) { Vector.reserve(Cap); }
115
116 // Element Access & Lookups
117
118 template <typename K> const_iterator find(const K &Key) const {
119 auto [It, Found] = find_or_insert_location(Key);
120 return Found ? It : Vector.end();
121 }
122
123 template <typename K> iterator find(const K &Key) {
124 auto [It, Found] = find_or_insert_location(Key);
125 return Found ? It : Vector.end();
126 }
127
128 template <typename... Ts>
129 std::pair<iterator, bool> try_emplace(const KeyT &Key, Ts &&...Args) {
130 return try_emplace_impl(Key, std::forward<Ts>(Args)...);
131 }
132
133 template <typename... Ts>
134 std::pair<iterator, bool> try_emplace(KeyT &&Key, Ts &&...Args) {
135 return try_emplace_impl(std::move(Key), std::forward<Ts>(Args)...);
136 }
137
138 std::pair<iterator, bool> insert(const value_type &KV) {
139 return try_emplace_impl(KV.first, KV.second);
140 }
141
142 std::pair<iterator, bool> insert(value_type &&KV) {
143 return try_emplace_impl(std::move(KV.first), std::move(KV.second));
144 }
145
146 ValueT &operator[](const KeyT &Key) {
147 return try_emplace_impl(Key).first->second;
148 }
149
150 ValueT &operator[](KeyT &&Key) {
151 return try_emplace_impl(std::move(Key)).first->second;
152 }
153
154 iterator erase(iterator Pos) { return Vector.erase(Pos); }
155 iterator erase(const_iterator Pos) { return Vector.erase(Pos); }
156
157 bool operator==(const SortedVectorMap &Other) const {
158 return Vector == Other.Vector;
159 }
160};
161} // namespace llvm
162
163#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
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
typename VectorType::iterator iterator
size_type capacity() const
void reserve(size_type Cap)
typename VectorType::const_iterator const_iterator
ValueT & operator[](const KeyT &Key)
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
ValueT & operator[](KeyT &&Key)
std::pair< iterator, bool > try_emplace(const KeyT &Key, Ts &&...Args)
size_type size() const
std::pair< KeyT, ValueT > value_type
const_iterator begin() const
iterator find(const K &Key)
SmallVector< value_type, N > VectorType
iterator erase(const_iterator Pos)
typename VectorType::size_type size_type
std::pair< iterator, bool > insert(const value_type &KV)
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