[llvm] [ADT] Restore handwritten vector find in SmallSet (PR #110254)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Sep 27 06:31:51 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-adt
Author: Victor Campos (vhscampos)
<details>
<summary>Changes</summary>
This patch restores handwritten linear searches instead of the use of std::find.
After PR #<!-- -->109412, a performance regression was observed that's caused by the use of std::find for linear searches.
The exact cause wasn't pinpointed, but, at the time of writing, the most likely culprit is the forced loop unrolling in the definition of libstdc++'s std::find. Presumably this is done to optimise for larger containers.
However for the case of small containers such as SmallVector, this actually hurts performance.
---
Full diff: https://github.com/llvm/llvm-project/pull/110254.diff
1 Files Affected:
- (modified) llvm/include/llvm/ADT/SmallSet.h (+10-4)
``````````diff
diff --git a/llvm/include/llvm/ADT/SmallSet.h b/llvm/include/llvm/ADT/SmallSet.h
index 97ea4c642bf556..3bc101882dab79 100644
--- a/llvm/include/llvm/ADT/SmallSet.h
+++ b/llvm/include/llvm/ADT/SmallSet.h
@@ -193,7 +193,7 @@ class SmallSet {
bool erase(const T &V) {
if (!isSmall())
return Set.erase(V);
- auto I = std::find(Vector.begin(), Vector.end(), V);
+ auto I = vfind(V);
if (I != Vector.end()) {
Vector.erase(I);
return true;
@@ -221,7 +221,7 @@ class SmallSet {
/// Check if the SmallSet contains the given element.
bool contains(const T &V) const {
if (isSmall())
- return std::find(Vector.begin(), Vector.end(), V) != Vector.end();
+ return vfind(V) != Vector.end();
return Set.find(V) != Set.end();
}
@@ -237,20 +237,26 @@ class SmallSet {
return {const_iterator(I), Inserted};
}
- auto I = std::find(Vector.begin(), Vector.end(), V);
+ auto I = vfind(V);
if (I != Vector.end()) // Don't reinsert if it already exists.
return {const_iterator(I), false};
if (Vector.size() < N) {
Vector.push_back(std::forward<ArgType>(V));
return {const_iterator(std::prev(Vector.end())), true};
}
-
// Otherwise, grow from vector to set.
Set.insert(std::make_move_iterator(Vector.begin()),
std::make_move_iterator(Vector.end()));
Vector.clear();
return {const_iterator(Set.insert(std::forward<ArgType>(V)).first), true};
}
+
+ auto vfind(const T &V) const {
+ for (auto I = Vector.begin(), E = Vector.end(); I != E; ++I)
+ if (*I == V)
+ return I;
+ return Vector.end();
+ }
};
/// If this set is of pointer values, transparently switch over to using
``````````
</details>
https://github.com/llvm/llvm-project/pull/110254
More information about the llvm-commits
mailing list