[PATCH] D84717: [ADT][BitVector] Merge find_first_in() / find_first_unset_in()
Stefanos Baziotis via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Mon Jul 27 17:47:49 PDT 2020
baziotis created this revision.
baziotis added reviewers: Meinersbur, RKSimon, zturner, lattner, MatzeB.
Herald added subscribers: llvm-commits, dexonsmith.
Herald added a project: LLVM.
We can implement `find_first_unset_in()` in the same way if every `BitWord` we use is first flipped.
Performance wise, it should be the same because the branch predictor will do a very good job
since `set` stays the same in a single run of the function. Plus, this won't even be a real
branch in x86, it will be just a `cmov`.
https://reviews.llvm.org/D84717
Files:
llvm/include/llvm/ADT/BitVector.h
Index: llvm/include/llvm/ADT/BitVector.h
===================================================================
--- llvm/include/llvm/ADT/BitVector.h
+++ llvm/include/llvm/ADT/BitVector.h
@@ -203,19 +203,25 @@
return !any();
}
- /// find_first_in - Returns the index of the first set bit in the range
- /// [Begin, End). Returns -1 if all bits in the range are unset.
- int find_first_in(unsigned Begin, unsigned End) const {
+ /// find_first_in - Returns the index of the first set / unset bit,
+ /// depending on \p set, in the range [Begin, End).
+ /// Returns -1 if all bits in the range are unset / set.
+ int find_first_in(unsigned Begin, unsigned End, bool set = true) const {
assert(Begin <= End && End <= Size);
if (Begin == End)
return -1;
+ auto getWord = [this, set](size_t i) {
+ BitWord Word = Bits[i];
+ return (set) ? Word : (~Word);
+ };
+
unsigned FirstWord = Begin / BITWORD_SIZE;
unsigned LastWord = (End - 1) / BITWORD_SIZE;
// Check subsequent words.
for (unsigned i = FirstWord; i <= LastWord; ++i) {
- BitWord Copy = Bits[i];
+ BitWord Copy = getWord(i);
if (i == FirstWord) {
unsigned FirstBit = Begin % BITWORD_SIZE;
@@ -266,32 +272,7 @@
/// find_first_unset_in - Returns the index of the first unset bit in the
/// range [Begin, End). Returns -1 if all bits in the range are set.
int find_first_unset_in(unsigned Begin, unsigned End) const {
- assert(Begin <= End && End <= Size);
- if (Begin == End)
- return -1;
-
- unsigned FirstWord = Begin / BITWORD_SIZE;
- unsigned LastWord = (End - 1) / BITWORD_SIZE;
-
- // Check subsequent words.
- for (unsigned i = FirstWord; i <= LastWord; ++i) {
- BitWord Copy = Bits[i];
-
- if (i == FirstWord) {
- unsigned FirstBit = Begin % BITWORD_SIZE;
- Copy |= maskTrailingOnes<BitWord>(FirstBit);
- }
-
- if (i == LastWord) {
- unsigned LastBit = (End - 1) % BITWORD_SIZE;
- Copy |= maskTrailingZeros<BitWord>(LastBit + 1);
- }
- if (Copy != ~BitWord(0)) {
- unsigned Result = i * BITWORD_SIZE + countTrailingOnes(Copy);
- return Result < size() ? Result : -1;
- }
- }
- return -1;
+ return find_first_in(Begin, End, /* set = */ false);
}
/// find_last_unset_in - Returns the index of the last unset bit in the
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D84717.281089.patch
Type: text/x-patch
Size: 2404 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20200728/e1557fd8/attachment.bin>
More information about the llvm-commits
mailing list