This is an archive of the discontinued LLVM Phabricator instance.

[SetVector] Implement better "small" functionality
ClosedPublic

Authored by 0xdc03 on Jun 8 2023, 10:33 PM.

Details

Summary

SmallSetVector has an inefficiency where it does set insertions
regardless of the number of elements present within it. This contrasts
with other "Small-" containers where they use linear scan up to a
certain size "N", after which they switch to another strategy.

This patch implements this functionality in SetVector, adding a template
parameter "N" which specifies the number of elements upto which the
SetVector follows the "small" strategy. Due to the use of "if
constexpr", there is no "small" code emitted when N is 0 which makes
this a zero overhead change for users using the default behaviour.

This change also allows having SmallSetVector use DenseSet instead of
SmallDenseSet by default, which helps a little with performance.

The reason for implementing this functionality in SetVector instead of
SmallSetVector is that it allows reusing all the code that is already
there and it is just augmented with the "isSmall" checks.

This change gives a good speedup (0.4%):
https://llvm-compile-time-tracker.com/compare.php?from=086601eac266ec253bf313c746390ff3e5656132&to=acd0a72a4d3ee840f7b455d1b35d82b11ffdb3c0&stat=instructions%3Au

Diff Detail

Event Timeline

0xdc03 created this revision.Jun 8 2023, 10:33 PM
Herald added a reviewer: ftynse. · View Herald Transcript
Herald added a reviewer: dcaballe. · View Herald Transcript
Herald added a project: Restricted Project. · View Herald Transcript
0xdc03 requested review of this revision.Jun 8 2023, 10:33 PM
Herald added projects: Restricted Project, Restricted Project. · View Herald TranscriptJun 8 2023, 10:33 PM

Just a note: even though this technically an NFC, it changes the functionality of SetVector a fair bit so I'm not sure if I should mark it as such.

nikic added a comment.Jun 9 2023, 12:22 AM

Apart from the note on the static_assert, this looks good to me. There's a significant compile-time improvement, a minor memory usage improvement, and even the size of the clang binary gets slightly smaller, so this seems like an improvement on all metrics for relatively little additional complexity.

llvm/include/llvm/ADT/SetVector.h
57–61

It might make sense to replicate this static_assert from SmallPtrSet: https://github.com/llvm/llvm-project/blob/ecbd37d5a336ec8a8adafae5a8e4263bb738718c/llvm/include/llvm/ADT/SmallPtrSet.h#L451-L454

To make sure people don't shoot themselves in the foot with a nice SmallSetVector<T, 512>.

From a quick grep, this is the only usage that would have to be adjusted: https://github.com/llvm/llvm-project/blob/ecbd37d5a336ec8a8adafae5a8e4263bb738718c/flang/lib/Lower/Bridge.cpp#L190

213–220

Could write it like this, not sure if better.

0xdc03 updated this revision to Diff 529889.Jun 9 2023, 3:25 AM
  • Address reviewer comments
  • Add comment explaining N
Herald added a project: Restricted Project. · View Herald TranscriptJun 9 2023, 3:25 AM
0xdc03 added inline comments.Jun 9 2023, 3:29 AM
llvm/include/llvm/ADT/SetVector.h
57–61

Done, though I'm unsure if its better to have a higher limit of N (for example SmallVector has no limits).

213–220

I do believe this would change the logic of the operation, because this would allow an empty set but non-empty vector to work as a well-defined SetVector when not in the small case while erasing. I think the correct check would be something like (canBeSmall() && isSmall()) || set_.count(V), which is also fine I guess.

0xdc03 updated this revision to Diff 529910.Jun 9 2023, 4:34 AM
  • Fix formatting
nikic accepted this revision.Jun 9 2023, 8:15 AM

LGTM

This revision is now accepted and ready to land.Jun 9 2023, 8:15 AM

Heads-up: This is causing some clang crash for some file internally at google. Working on a reduced case.