Skip to content

Commit e0295a1

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 a2438ce commit e0295a1

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
@@ -165,26 +165,10 @@ class SmallSet {
165165
/// Returns a pair. The first value of it is an iterator to the inserted
166166
/// element or the existing element in the set. The second value is true
167167
/// if the element is inserted (it was not in the set before).
168-
std::pair<const_iterator, bool> insert(const T &V) {
169-
if (!isSmall()) {
170-
auto [I, Inserted] = Set.insert(V);
171-
return std::make_pair(const_iterator(I), Inserted);
172-
}
168+
std::pair<const_iterator, bool> insert(const T &V) { return insertImpl(V); }
173169

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

190174
template <typename IterT>
@@ -231,6 +215,31 @@ class SmallSet {
231215

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

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

0 commit comments

Comments
 (0)