Skip to content

Commit fffe272

Browse files
[ADT] Make set_subtract more efficient when subtrahend is larger (NFC) (#98702)
If the subtrahend is larger, iterate the minuend set instead. Noticed when subtracting a large set from a number of other smaller sets for an upcoming MemProf change, this change makes that much faster. I subsequently found a couple of callsites in one file that were calling set_subtract with a vector subtrahend, which doesn't have the "count()" interface. Add a separate helper for subtracting a vector.
1 parent 33cb29c commit fffe272

File tree

1 file changed

+15
-0
lines changed

1 file changed

+15
-0
lines changed

llvm/include/llvm/ADT/SetOperations.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,22 @@ S1Ty set_difference(const S1Ty &S1, const S2Ty &S2) {
9494

9595
/// set_subtract(A, B) - Compute A := A - B
9696
///
97+
/// Selects the set to iterate based on the relative sizes of A and B for better
98+
/// efficiency.
99+
///
97100
template <class S1Ty, class S2Ty> void set_subtract(S1Ty &S1, const S2Ty &S2) {
101+
using ElemTy = decltype(*S1.begin());
102+
// A couple callers pass a vector for S2, which doesn't support contains(),
103+
// and wouldn't be efficient if it did.
104+
if constexpr (detail::HasMemberContains<S2Ty, ElemTy>) {
105+
if (S1.size() < S2.size()) {
106+
for (typename S1Ty::iterator SI = S1.begin(), SE = S1.end(); SI != SE;
107+
++SI)
108+
if (S2.contains(*SI))
109+
S1.erase(SI);
110+
return;
111+
}
112+
}
98113
for (typename S2Ty::const_iterator SI = S2.begin(), SE = S2.end(); SI != SE;
99114
++SI)
100115
S1.erase(*SI);

0 commit comments

Comments
 (0)