From 53bb5c009b04f4a5dd2388b25efe88b5579b282c Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Fri, 26 Nov 2010 06:54:20 +0000 Subject: [PATCH] Add B+-tree test case that creates a height 3 tree with a smaller root node. Change temporary debugging code to write a dot file directly. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@120171 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/ADT/IntervalMap.h | 46 ++++++++++++++++++---------- unittests/ADT/IntervalMapTest.cpp | 51 +++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+), 16 deletions(-) diff --git a/include/llvm/ADT/IntervalMap.h b/include/llvm/ADT/IntervalMap.h index dcc30f033c8..8eb5487b0e4 100644 --- a/include/llvm/ADT/IntervalMap.h +++ b/include/llvm/ADT/IntervalMap.h @@ -585,11 +585,11 @@ public: unsigned extendStop(unsigned i, unsigned Size, KeyT b); #ifndef NDEBUG - void dump(unsigned Size) { - errs() << " N" << this << " [shape=record label=\"{ " << Size << '/' << N; + void dump(raw_ostream &OS, unsigned Size) { + OS << " N" << this << " [shape=record label=\"{ " << Size << '/' << N; for (unsigned i = 0; i != Size; ++i) - errs() << " | {" << start(i) << '-' << stop(i) << "|" << value(i) << '}'; - errs() << "}\"];\n"; + OS << " | {" << start(i) << '-' << stop(i) << "|" << value(i) << '}'; + OS << "}\"];\n"; } #endif @@ -771,14 +771,14 @@ public: } #ifndef NDEBUG - void dump(unsigned Size) { - errs() << " N" << this << " [shape=record label=\"" << Size << '/' << N; + void dump(raw_ostream &OS, unsigned Size) { + OS << " N" << this << " [shape=record label=\"" << Size << '/' << N; for (unsigned i = 0; i != Size; ++i) - errs() << " | " << stop(i); - errs() << "\"];\n"; + OS << " | " << stop(i); + OS << "\"];\n"; for (unsigned i = 0; i != Size; ++i) - errs() << " N" << this << ":s" << i << " -> N" - << &subtree(i).template get() << ";\n"; + OS << " N" << this << ":s" << i << " -> N" + << &subtree(i).template get() << ";\n"; } #endif @@ -851,6 +851,12 @@ public: return path[Level].subtree(path[Level].offset); } + /// reset - Reset cached information about node(Level) from subtree(Level -1). + /// @param Level 1..height. THe node to update after parent node changed. + void reset(unsigned Level) { + path[Level] = Entry(subtree(Level - 1), offset(Level)); + } + /// push - Add entry to path. /// @param Node Node to add, should be subtree(path.size()-1). /// @param Offset Offset into Node. @@ -1167,6 +1173,7 @@ public: } #ifndef NDEBUG + raw_ostream *OS; void dump(); void dumpNode(IntervalMapImpl::NodeRef Node, unsigned Height); #endif @@ -1316,21 +1323,24 @@ template void IntervalMap:: dumpNode(IntervalMapImpl::NodeRef Node, unsigned Height) { if (Height) - Node.get().dump(Node.size()); + Node.get().dump(*OS, Node.size()); else - Node.get().dump(Node.size()); + Node.get().dump(*OS, Node.size()); } template void IntervalMap:: dump() { - errs() << "digraph {\n"; + std::string errors; + raw_fd_ostream ofs("tree.dot", errors); + OS = &ofs; + ofs << "digraph {\n"; if (branched()) - rootBranch().dump(rootSize); + rootBranch().dump(ofs, rootSize); else - rootLeaf().dump(rootSize); + rootLeaf().dump(ofs, rootSize); visitNodes(&IntervalMap::dumpNode); - errs() << "}\n"; + ofs << "}\n"; } #endif @@ -1557,6 +1567,7 @@ iterator::insertNode(unsigned Level, IntervalMapImpl::NodeRef Node, KeyT Stop) { if (IM.rootSize < RootBranch::Capacity) { IM.rootBranch().insert(P.offset(0), IM.rootSize, Node, Stop); P.setSize(0, ++IM.rootSize); + P.reset(Level); return SplitRoot; } @@ -1581,6 +1592,9 @@ iterator::insertNode(unsigned Level, IntervalMapImpl::NodeRef Node, KeyT Stop) { } P.node(Level).insert(P.offset(Level), P.size(Level), Node, Stop); P.setSize(Level, P.size(Level) + 1); + if (P.atLastBranch(Level)) + setNodeStop(Level, Stop); + P.reset(Level + 1); return SplitRoot; } diff --git a/unittests/ADT/IntervalMapTest.cpp b/unittests/ADT/IntervalMapTest.cpp index d4b2f52b50c..36476a4cad9 100644 --- a/unittests/ADT/IntervalMapTest.cpp +++ b/unittests/ADT/IntervalMapTest.cpp @@ -15,6 +15,7 @@ using namespace llvm; namespace { typedef IntervalMap UUMap; +typedef IntervalMap UU4Map; // Empty map tests TEST(IntervalMapTest, EmptyMap) { @@ -373,4 +374,54 @@ TEST(IntervalMapTest, Branched) { EXPECT_TRUE(map.begin() == map.end()); } +// Branched, high, non-coalescing tests. +TEST(IntervalMapTest, Branched2) { + UU4Map::Allocator allocator; + UU4Map map(allocator); + + // Insert enough intervals to force a height >= 2 tree. + for (unsigned i = 1; i < 1000; ++i) + map.insert(10*i, 10*i+5, i); + + // Tree limits. + EXPECT_FALSE(map.empty()); + EXPECT_EQ(10u, map.start()); + EXPECT_EQ(9995u, map.stop()); + + // Tree lookup. + for (unsigned i = 1; i < 1000; ++i) { + EXPECT_EQ(0u, map.lookup(10*i-1)); + EXPECT_EQ(i, map.lookup(10*i)); + EXPECT_EQ(i, map.lookup(10*i+5)); + EXPECT_EQ(0u, map.lookup(10*i+6)); + } + + // Forward iteration. + UU4Map::iterator I = map.begin(); + for (unsigned i = 1; i < 1000; ++i) { + ASSERT_TRUE(I.valid()); + EXPECT_EQ(10*i, I.start()); + EXPECT_EQ(10*i+5, I.stop()); + EXPECT_EQ(i, *I); + ++I; + } + EXPECT_FALSE(I.valid()); + EXPECT_TRUE(I == map.end()); + + // Backwards iteration. + for (unsigned i = 999; i; --i) { + --I; + ASSERT_TRUE(I.valid()); + EXPECT_EQ(10*i, I.start()); + EXPECT_EQ(10*i+5, I.stop()); + EXPECT_EQ(i, *I); + } + EXPECT_TRUE(I == map.begin()); + + // Test clear() on branched map. + map.clear(); + EXPECT_TRUE(map.empty()); + EXPECT_TRUE(map.begin() == map.end()); +} + } // namespace