Skip to content

Commit 4974861

Browse files
committed
[ADT] Use perfect forwarding in SmallSet::insert()
Previously this method took arguments by const-ref. This patch changes the implementation to take perfectly forwarded arguments in the form of a universal reference. Now, the insertion method will take advantage of arguments passed as rvalue, potentially leading to performance improvements.
1 parent ce6c236 commit 4974861

File tree

1 file changed

+28
-19
lines changed

1 file changed

+28
-19
lines changed

llvm/include/llvm/ADT/SmallSet.h

Lines changed: 28 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -161,26 +161,10 @@ class SmallSet {
161161
/// Returns a pair. The first value of it is an iterator to the inserted
162162
/// element or the existing element in the set. The second value is true
163163
/// if the element is inserted (it was not in the set before).
164-
std::pair<const_iterator, bool> insert(const T &V) {
165-
if (!isSmall()) {
166-
auto [I, Inserted] = Set.insert(V);
167-
return std::make_pair(const_iterator(I), Inserted);
168-
}
164+
std::pair<const_iterator, bool> insert(const T &V) { return insertImpl(V); }
169165

170-
auto I = std::find(Vector.begin(), Vector.end(), V);
171-
if (I != Vector.end()) // Don't reinsert if it already exists.
172-
return std::make_pair(const_iterator(I), false);
173-
if (Vector.size() < N) {
174-
Vector.push_back(V);
175-
return std::make_pair(const_iterator(std::prev(Vector.end())), true);
176-
}
177-
178-
// Otherwise, grow from vector to set.
179-
while (!Vector.empty()) {
180-
Set.insert(Vector.back());
181-
Vector.pop_back();
182-
}
183-
return std::make_pair(const_iterator(Set.insert(V).first), true);
166+
std::pair<const_iterator, bool> insert(T &&V) {
167+
return insertImpl(std::move(V));
184168
}
185169

186170
template <typename IterT>
@@ -226,6 +210,31 @@ class SmallSet {
226210

227211
private:
228212
bool isSmall() const { return Set.empty(); }
213+
214+
template <typename ArgType>
215+
std::pair<const_iterator, bool> insertImpl(ArgType &&V) {
216+
static_assert(std::is_convertible_v<ArgType, T>,
217+
"ArgType must be convertible to T!");
218+
if (!isSmall()) {
219+
auto [I, Inserted] = Set.insert(std::forward<ArgType>(V));
220+
return std::make_pair(const_iterator(I), Inserted);
221+
}
222+
223+
auto I = std::find(Vector.begin(), Vector.end(), V);
224+
if (I != Vector.end()) // Don't reinsert if it already exists.
225+
return std::make_pair(const_iterator(I), false);
226+
if (Vector.size() < N) {
227+
Vector.push_back(std::forward<ArgType>(V));
228+
return std::make_pair(const_iterator(std::prev(Vector.end())), true);
229+
}
230+
231+
// Otherwise, grow from vector to set.
232+
Set.insert(std::make_move_iterator(Vector.begin()),
233+
std::make_move_iterator(Vector.end()));
234+
Vector.clear();
235+
return std::make_pair(
236+
const_iterator(Set.insert(std::forward<ArgType>(V)).first), true);
237+
}
229238
};
230239

231240
/// If this set is of pointer values, transparently switch over to using

0 commit comments

Comments
 (0)