summaryrefslogtreecommitdiffstats
path: root/clang-tools-extra/unittests/clangd/DexTests.cpp
diff options
context:
space:
mode:
authorSam McCall <sam.mccall@gmail.com>2018-10-04 13:12:23 +0000
committerSam McCall <sam.mccall@gmail.com>2018-10-04 13:12:23 +0000
commit87f69eaf4e5022aa98b4b8c340efb72101fd16f5 (patch)
treece4f11a633ad7793d75dc2d1229a3443ab84b7f9 /clang-tools-extra/unittests/clangd/DexTests.cpp
parent82a3b1c687472d805498276cfb0a41f4c3e616e2 (diff)
downloadbcm5719-llvm-87f69eaf4e5022aa98b4b8c340efb72101fd16f5.tar.gz
bcm5719-llvm-87f69eaf4e5022aa98b4b8c340efb72101fd16f5.zip
[clangd] Dex: FALSE iterator, peephole optimizations, fix AND bug
Summary: The FALSE iterator will be used in a followup patch to fix a logic bug in Dex (currently, tokens that don't have posting lists in the index are simply dropped from the query, changing semantics). It can usually be optimized away, so added the following opmitizations: - simplify booleans inside AND/OR - replace effectively-empty AND/OR with booleans - flatten nested AND/ORs While working on this, found a bug in the AND iterator: its constructor sync() assumes that ReachedEnd is set if applicable, but the constructor never sets it. This crashes if a non-first iterator is nonempty. Reviewers: ilya-biryukov Subscribers: ioeric, MaskRay, jkorous, arphaman, kadircet, cfe-commits Differential Revision: https://reviews.llvm.org/D52789 llvm-svn: 343774
Diffstat (limited to 'clang-tools-extra/unittests/clangd/DexTests.cpp')
-rw-r--r--clang-tools-extra/unittests/clangd/DexTests.cpp58
1 files changed, 46 insertions, 12 deletions
diff --git a/clang-tools-extra/unittests/clangd/DexTests.cpp b/clang-tools-extra/unittests/clangd/DexTests.cpp
index d1d5b4c7eeb..c36573c1a80 100644
--- a/clang-tools-extra/unittests/clangd/DexTests.cpp
+++ b/clang-tools-extra/unittests/clangd/DexTests.cpp
@@ -109,6 +109,18 @@ TEST(DexIterators, AndThreeLists) {
EXPECT_TRUE(And->reachedEnd());
}
+TEST(DexIterators, AndEmpty) {
+ Corpus C{10000};
+ const PostingList L1({1});
+ const PostingList L2({2});
+ // These iterators are empty, but the optimizer can't tell.
+ auto Empty1 = C.intersect(L1.iterator(), L2.iterator());
+ auto Empty2 = C.intersect(L1.iterator(), L2.iterator());
+ // And syncs iterators on construction, and used to fail on empty children.
+ auto And = C.intersect(std::move(Empty1), std::move(Empty2));
+ EXPECT_TRUE(And->reachedEnd());
+}
+
TEST(DexIterators, OrTwoLists) {
Corpus C{10000};
const PostingList L0({0, 5, 7, 10, 42, 320, 9000});
@@ -270,18 +282,8 @@ TEST(DexIterators, Limit) {
}
TEST(DexIterators, True) {
- Corpus C{0};
- auto TrueIterator = C.all();
- EXPECT_TRUE(TrueIterator->reachedEnd());
- EXPECT_THAT(consumeIDs(*TrueIterator), ElementsAre());
-
- C = Corpus{7};
- const PostingList L0({1, 2, 5, 7});
- TrueIterator = C.all();
- EXPECT_THAT(TrueIterator->peek(), 0);
- auto AndIterator = C.intersect(L0.iterator(), move(TrueIterator));
- EXPECT_FALSE(AndIterator->reachedEnd());
- EXPECT_THAT(consumeIDs(*AndIterator), ElementsAre(1, 2, 5));
+ EXPECT_TRUE(Corpus{0}.all()->reachedEnd());
+ EXPECT_THAT(consumeIDs(*Corpus{4}.all()), ElementsAre(0, 1, 2, 3));
}
TEST(DexIterators, Boost) {
@@ -313,6 +315,38 @@ TEST(DexIterators, Boost) {
EXPECT_THAT(ElementBoost, 3);
}
+TEST(DexIterators, Optimizations) {
+ Corpus C{5};
+ const PostingList L1({1});
+ const PostingList L2({2});
+ const PostingList L3({3});
+
+ // empty and/or yield true/false
+ EXPECT_EQ(llvm::to_string(*C.intersect()), "true");
+ EXPECT_EQ(llvm::to_string(*C.unionOf()), "false");
+
+ // true/false inside and/or short-circuit
+ EXPECT_EQ(llvm::to_string(*C.intersect(L1.iterator(), C.all())), "[1]");
+ EXPECT_EQ(llvm::to_string(*C.intersect(L1.iterator(), C.none())), "false");
+ // Not optimized to avoid breaking boosts.
+ EXPECT_EQ(llvm::to_string(*C.unionOf(L1.iterator(), C.all())),
+ "(| [1] true)");
+ EXPECT_EQ(llvm::to_string(*C.unionOf(L1.iterator(), C.none())), "[1]");
+
+ // and/or nested inside and/or are flattened
+ EXPECT_EQ(llvm::to_string(*C.intersect(
+ L1.iterator(), C.intersect(L1.iterator(), L1.iterator()))),
+ "(& [1] [1] [1])");
+ EXPECT_EQ(llvm::to_string(*C.unionOf(
+ L1.iterator(), C.unionOf(L2.iterator(), L3.iterator()))),
+ "(| [1] [2] [3])");
+
+ // optimizations combine over multiple levels
+ EXPECT_EQ(llvm::to_string(*C.intersect(
+ C.intersect(L1.iterator(), C.intersect()), C.unionOf(C.all()))),
+ "[1]");
+}
+
//===----------------------------------------------------------------------===//
// Search token tests.
//===----------------------------------------------------------------------===//
OpenPOWER on IntegriCloud