summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Sanders <daniel_l_sanders@apple.com>2018-10-31 20:05:32 +0000
committerDaniel Sanders <daniel_l_sanders@apple.com>2018-10-31 20:05:32 +0000
commitf777e8b463da352e63679bfa7968cbec7468f1f9 (patch)
tree8b7f93667c77477943e5d8203e97af5f50088866
parentb041831a1adaba180cad8d47de8f5a90b38de42b (diff)
downloadbcm5719-llvm-f777e8b463da352e63679bfa7968cbec7468f1f9.tar.gz
bcm5719-llvm-f777e8b463da352e63679bfa7968cbec7468f1f9.zip
[adt] SparseBitVector::test() should be const
Summary: Re-worked SparseBitVector's most-recently-used-word caching (CurrElementIter) such that SparseBitVector::test() can be made const. This came up when attempting to test individual bits in a SparseBitVector which was a member of a const object. The cached iterator has no bearing on the externally visible state, it's merely a performance optimization. Therefore it has been made mutable and FindLowerBound() has been split into a const and non-const function (FindLowerBound/FindLowerBoundConst) for the const/non-const interfaces. Reviewers: rtereshin Reviewed By: rtereshin Subscribers: rtereshin, dexonsmith, kristina, llvm-commits Differential Revision: https://reviews.llvm.org/D53447 llvm-svn: 345772
-rw-r--r--llvm/include/llvm/ADT/SparseBitVector.h38
-rw-r--r--llvm/unittests/ADT/SparseBitVectorTest.cpp5
2 files changed, 33 insertions, 10 deletions
diff --git a/llvm/include/llvm/ADT/SparseBitVector.h b/llvm/include/llvm/ADT/SparseBitVector.h
index 4cbf40c7680..09a91b6614e 100644
--- a/llvm/include/llvm/ADT/SparseBitVector.h
+++ b/llvm/include/llvm/ADT/SparseBitVector.h
@@ -261,21 +261,33 @@ class SparseBitVector {
BITWORD_SIZE = SparseBitVectorElement<ElementSize>::BITWORD_SIZE
};
- // Pointer to our current Element.
- ElementListIter CurrElementIter;
+ // Pointer to our current Element. This has no visible effect on the external
+ // state of a SparseBitVector, it's just used to improve performance in the
+ // common case of testing/modifying bits with similar indices.
+ mutable ElementListIter CurrElementIter;
ElementList Elements;
// This is like std::lower_bound, except we do linear searching from the
// current position.
- ElementListIter FindLowerBound(unsigned ElementIndex) {
+ ElementListIter FindLowerBoundImpl(unsigned ElementIndex) const {
+
+ // We cache a non-const iterator so we're forced to resort to const_cast to
+ // get the begin/end in the case where 'this' is const. To avoid duplication
+ // of code with the only difference being whether the const cast is present
+ // 'this' is always const in this particular function and we sort out the
+ // difference in FindLowerBound and FindLowerBoundConst.
+ ElementListIter Begin =
+ const_cast<SparseBitVector<ElementSize> *>(this)->Elements.begin();
+ ElementListIter End =
+ const_cast<SparseBitVector<ElementSize> *>(this)->Elements.end();
if (Elements.empty()) {
- CurrElementIter = Elements.begin();
- return Elements.begin();
+ CurrElementIter = Begin;
+ return CurrElementIter;
}
// Make sure our current iterator is valid.
- if (CurrElementIter == Elements.end())
+ if (CurrElementIter == End)
--CurrElementIter;
// Search from our current iterator, either backwards or forwards,
@@ -284,17 +296,23 @@ class SparseBitVector {
if (CurrElementIter->index() == ElementIndex) {
return ElementIter;
} else if (CurrElementIter->index() > ElementIndex) {
- while (ElementIter != Elements.begin()
+ while (ElementIter != Begin
&& ElementIter->index() > ElementIndex)
--ElementIter;
} else {
- while (ElementIter != Elements.end() &&
+ while (ElementIter != End &&
ElementIter->index() < ElementIndex)
++ElementIter;
}
CurrElementIter = ElementIter;
return ElementIter;
}
+ ElementListConstIter FindLowerBoundConst(unsigned ElementIndex) const {
+ return FindLowerBoundImpl(ElementIndex);
+ }
+ ElementListIter FindLowerBound(unsigned ElementIndex) {
+ return FindLowerBoundImpl(ElementIndex);
+ }
// Iterator to walk set bits in the bitmap. This iterator is a lot uglier
// than it would be, in order to be efficient.
@@ -464,12 +482,12 @@ public:
}
// Test, Reset, and Set a bit in the bitmap.
- bool test(unsigned Idx) {
+ bool test(unsigned Idx) const {
if (Elements.empty())
return false;
unsigned ElementIndex = Idx / ElementSize;
- ElementListIter ElementIter = FindLowerBound(ElementIndex);
+ ElementListConstIter ElementIter = FindLowerBoundConst(ElementIndex);
// If we can't find an element that is supposed to contain this bit, there
// is nothing more to do.
diff --git a/llvm/unittests/ADT/SparseBitVectorTest.cpp b/llvm/unittests/ADT/SparseBitVectorTest.cpp
index 9d6f4f1665d..097f4a0b737 100644
--- a/llvm/unittests/ADT/SparseBitVectorTest.cpp
+++ b/llvm/unittests/ADT/SparseBitVectorTest.cpp
@@ -31,6 +31,11 @@ TEST(SparseBitVectorTest, TrivialOperation) {
EXPECT_TRUE(Vec.test(17));
Vec.clear();
EXPECT_FALSE(Vec.test(17));
+
+ Vec.set(5);
+ const SparseBitVector<> ConstVec = Vec;
+ EXPECT_TRUE(ConstVec.test(5));
+ EXPECT_FALSE(ConstVec.test(17));
}
TEST(SparseBitVectorTest, IntersectWith) {
OpenPOWER on IntegriCloud