llvm.org GIT mirror llvm / 706da9d
Move tree navigation to a new Path class that doesn't have to be a template. The path also holds a reference to the root node, and that allows important iterator accessors like start() and stop() to have no conditional code. (When the compiler is clever enough to remove it.) git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@120165 91177308-0d34-0410-b5e6-96231b3b80d8 Jakob Stoklund Olesen 9 years ago
2 changed file(s) with 370 addition(s) and 302 deletion(s). Raw diff Collapse all Expand all
402402 /// subtree - Access the i'th subtree reference in a branch node.
403403 /// This depends on branch nodes storing the NodeRef array as their first
404404 /// member.
405 NodeRef &subtree(unsigned i) {
405 NodeRef &subtree(unsigned i) const {
406406 return reinterpret_cast(pip.getPointer())[i];
407407 }
408408
698698
699699 };
700700
701 //===----------------------------------------------------------------------===//
702 //--- Path ---//
703 //===----------------------------------------------------------------------===//
704 //
705 // A Path is used by iterators to represent a position in a B+-tree, and the
706 // path to get there from the root.
707 //
708 // The Path class also constains the tree navigation code that doesn't have to
709 // be templatized.
710 //
711 //===----------------------------------------------------------------------===//
712
713 class Path {
714 /// Entry - Each step in the path is a node pointer and an offset into that
715 /// node.
716 struct Entry {
717 void *node;
718 unsigned size;
719 unsigned offset;
720
721 Entry(void *Node, unsigned Size, unsigned Offset)
722 : node(Node), size(Size), offset(Offset) {}
723
724 Entry(NodeRef Node, unsigned Offset)
725 : node(&Node.subtree(0)), size(Node.size()), offset(Offset) {}
726
727 NodeRef &subtree(unsigned i) const {
728 return reinterpret_cast(node)[i];
729 }
730 };
731
732 /// path - The path entries, path[0] is the root node, path.back() is a leaf.
733 SmallVector path;
734
735 public:
736 // Node accessors.
737 template NodeT &node(unsigned Level) const {
738 return *reinterpret_cast(path[Level].node);
739 }
740 unsigned size(unsigned Level) const { return path[Level].size; }
741 unsigned offset(unsigned Level) const { return path[Level].offset; }
742 unsigned &offset(unsigned Level) { return path[Level].offset; }
743
744 // Leaf accessors.
745 template NodeT &leaf() const {
746 return *reinterpret_cast(path.back().node);
747 }
748 unsigned leafSize() const { return path.back().size; }
749 unsigned leafOffset() const { return path.back().offset; }
750 unsigned &leafOffset() { return path.back().offset; }
751
752 /// valid - Return true if path is at a valid node, not at end().
753 bool valid() const {
754 return !path.empty() && path.front().offset < path.front().size;
755 }
756
757 /// height - Return the height of the tree corresponding to this path.
758 /// This matches map->height in a full path.
759 unsigned height() const { return path.size() - 1; }
760
761 /// subtree - Get the subtree referenced from Level. When the path is
762 /// consistent, node(Level + 1) == subtree(Level).
763 /// @param Level 0..height-1. The leaves have no subtrees.
764 NodeRef &subtree(unsigned Level) const {
765 return path[Level].subtree(path[Level].offset);
766 }
767
768 /// push - Add entry to path.
769 /// @param Node Node to add, should be subtree(path.size()-1).
770 /// @param Offset Offset into Node.
771 void push(NodeRef Node, unsigned Offset) {
772 path.push_back(Entry(Node, Offset));
773 }
774
775 /// setSize - Set the size of a node both in the path and in the tree.
776 /// @param Level 0..height. Note that setting the root size won't change
777 /// map->rootSize.
778 /// @param Size New node size.
779 void setSize(unsigned Level, unsigned Size) {
780 path[Level].size = Size;
781 if (Level)
782 subtree(Level - 1).setSize(Size);
783 }
784
785 /// setRoot - Clear the path and set a new root node.
786 /// @param Node New root node.
787 /// @param Size New root size.
788 /// @param Offset Offset into root node.
789 void setRoot(void *Node, unsigned Size, unsigned Offset) {
790 path.clear();
791 path.push_back(Entry(Node, Size, Offset));
792 }
793
794 /// replaceRoot - Replace the current root node with two new entries after the
795 /// tree height has increased.
796 /// @param Root The new root node.
797 /// @param Size Number of entries in the new root.
798 /// @param Offsets Offsets into the root and first branch nodes.
799 void replaceRoot(void *Root, unsigned Size, IdxPair Offsets);
800
801 /// getLeftSibling - Get the left sibling node at Level, or a null NodeRef.
802 /// @param Level Get the sibling to node(Level).
803 /// @return Left sibling, or NodeRef().
804 NodeRef getLeftSibling(unsigned Level) const;
805
806 /// moveLeft - Move path to the left sibling at Level. Leave nodes below Level
807 /// unaltered.
808 /// @param Level Move node(Level).
809 void moveLeft(unsigned Level);
810
811 /// fillLeft - Grow path to Height by taking leftmost branches.
812 /// @param Height The target height.
813 void fillLeft(unsigned Height) {
814 while (height() < Height)
815 push(subtree(height()), 0);
816 }
817
818 /// getLeftSibling - Get the left sibling node at Level, or a null NodeRef.
819 /// @param Level Get the sinbling to node(Level).
820 /// @return Left sibling, or NodeRef().
821 NodeRef getRightSibling(unsigned Level) const;
822
823 /// moveRight - Move path to the left sibling at Level. Leave nodes below
824 /// Level unaltered.
825 /// @param Level Move node(Level).
826 void moveRight(unsigned Level);
827
828 /// atLastBranch - Return true if the path is at the last branch of the node
829 /// at Level.
830 /// @param Level Node to examine.
831 bool atLastBranch(unsigned Level) const {
832 return path[Level].offset == path[Level].size - 1;
833 }
834
835 /// legalizeForInsert - Prepare the path for an insertion at Level. When the
836 /// path is at end(), node(Level) may not be a legal node. legalizeForInsert
837 /// ensures that node(Level) is real by moving back to the last node at Level,
838 /// and setting offset(Level) to size(Level) if required.
839 /// @param Level The level where an insertion is about to take place.
840 void legalizeForInsert(unsigned Level) {
841 if (valid())
842 return;
843 moveLeft(Level);
844 ++path[Level].offset;
845 }
846
847 #ifndef NDEBUG
848 void dump() const {
849 for (unsigned l = 0, e = path.size(); l != e; ++l)
850 errs() << l << ": " << path[l].node << ' ' << path[l].size << ' '
851 << path[l].offset << '\n';
852 }
853 #endif
854 };
855
701856 } // namespace IntervalMapImpl
702857
703858
11021257 public std::iterator {
11031258 protected:
11041259 friend class IntervalMap;
1105 typedef std::pair PathEntry;
1106 typedef SmallVector Path;
11071260
11081261 // The map referred to.
11091262 IntervalMap *map;
11101263
1111 // The offset into map's root node.
1112 unsigned rootOffset;
1113
11141264 // We store a full path from the root to the current position.
1115 //
1116 // When rootOffset == map->rootSize, we are at end() and path() is empty.
1117 // Otherwise, when branched these conditions hold:
1118 //
1119 // 1. path.front().first == rootBranch().subtree(rootOffset)
1120 // 2. path[i].first == path[i-1].first.subtree(path[i-1].second)
1121 // 3. path.size() == map->height.
1122 //
1123 // Thus, path.back() always refers to the current leaf node unless the root is
1124 // unbranched.
1125 //
11261265 // The path may be partially filled, but never between iterator calls.
1127 Path path;
1128
1129 explicit const_iterator(IntervalMap &map)
1130 : map(&map), rootOffset(map.rootSize) {}
1266 IntervalMapImpl::Path path;
1267
1268 explicit const_iterator(IntervalMap &map) : map(&map) {}
11311269
11321270 bool branched() const {
11331271 assert(map && "Invalid iterator");
11341272 return map->branched();
11351273 }
11361274
1137 IntervalMapImpl::NodeRef pathNode(unsigned h) const { return path[h].first; }
1138 IntervalMapImpl::NodeRef &pathNode(unsigned h) { return path[h].first; }
1139 unsigned pathOffset(unsigned h) const { return path[h].second; }
1140 unsigned &pathOffset(unsigned h) { return path[h].second; }
1141
1142 Leaf &treeLeaf() const {
1143 assert(branched() && path.size() == map->height);
1144 return path.back().first.template get();
1145 }
1146 unsigned treeLeafSize() const {
1147 assert(branched() && path.size() == map->height);
1148 return path.back().first.size();
1149 }
1150 unsigned &treeLeafOffset() {
1151 assert(branched() && path.size() == map->height);
1152 return path.back().second;
1153 }
1154 unsigned treeLeafOffset() const {
1155 assert(branched() && path.size() == map->height);
1156 return path.back().second;
1157 }
1158
1159 // Get the next node ptr for an incomplete path.
1160 IntervalMapImpl::NodeRef pathNextDown() {
1161 assert(path.size() < map->height && "Path is already complete");
1162
1163 if (path.empty())
1164 return map->rootBranch().subtree(rootOffset);
1275 void setRoot(unsigned Offset) {
1276 if (branched())
1277 path.setRoot(&map->rootBranch(), map->rootSize, Offset);
11651278 else
1166 return path.back().first.subtree(path.back().second);
1167 }
1168
1169 void pathFillLeft();
1279 path.setRoot(&map->rootLeaf(), map->rootSize, Offset);
1280 }
1281
11701282 void pathFillFind(KeyT x);
1171 void pathFillRight();
1172
1173 IntervalMapImpl::NodeRef leftSibling(unsigned level) const;
1174 IntervalMapImpl::NodeRef rightSibling(unsigned level) const;
1175
1176 void treeIncrement();
1177 void treeDecrement();
11781283 void treeFind(KeyT x);
11791284
11801285 public:
11811286 /// valid - Return true if the current position is valid, false for end().
1182 bool valid() const {
1183 assert(map && "Invalid iterator");
1184 return rootOffset < map->rootSize;
1185 }
1287 bool valid() const { return path.valid(); }
11861288
11871289 /// start - Return the beginning of the current interval.
11881290 const KeyT &start() const {
11891291 assert(valid() && "Cannot access invalid iterator");
1190 return branched() ? treeLeaf().start(treeLeafOffset()) :
1191 map->rootLeaf().start(rootOffset);
1292 return branched() ? path.leaf().start(path.leafOffset()) :
1293 path.leaf().start(path.leafOffset());
11921294 }
11931295
11941296 /// stop - Return the end of the current interval.
11951297 const KeyT &stop() const {
11961298 assert(valid() && "Cannot access invalid iterator");
1197 return branched() ? treeLeaf().stop(treeLeafOffset()) :
1198 map->rootLeaf().stop(rootOffset);
1299 return branched() ? path.leaf().stop(path.leafOffset()) :
1300 path.leaf().stop(path.leafOffset());
11991301 }
12001302
12011303 /// value - Return the mapped value at the current interval.
12021304 const ValT &value() const {
12031305 assert(valid() && "Cannot access invalid iterator");
1204 return branched() ? treeLeaf().value(treeLeafOffset()) :
1205 map->rootLeaf().value(rootOffset);
1306 return branched() ? path.leaf().value(path.leafOffset()) :
1307 path.leaf().value(path.leafOffset());
12061308 }
12071309
12081310 const ValT &operator*() const {
12111313
12121314 bool operator==(const const_iterator &RHS) const {
12131315 assert(map == RHS.map && "Cannot compare iterators from different maps");
1214 return rootOffset == RHS.rootOffset &&
1215 (!valid() || !branched() || path.back() == RHS.path.back());
1316 if (!valid())
1317 return !RHS.valid();
1318 if (path.leafOffset() != RHS.path.leafOffset())
1319 return false;
1320 return &path.template leaf() == &RHS.path.template leaf();
12161321 }
12171322
12181323 bool operator!=(const const_iterator &RHS) const {
12211326
12221327 /// goToBegin - Move to the first interval in map.
12231328 void goToBegin() {
1224 rootOffset = 0;
1225 path.clear();
1329 setRoot(0);
12261330 if (branched())
1227 pathFillLeft();
1331 path.fillLeft(map->height);
12281332 }
12291333
12301334 /// goToEnd - Move beyond the last interval in map.
12311335 void goToEnd() {
1232 rootOffset = map->rootSize;
1233 path.clear();
1336 setRoot(map->rootSize);
12341337 }
12351338
12361339 /// preincrement - move to the next interval.
12371340 const_iterator &operator++() {
12381341 assert(valid() && "Cannot increment end()");
1239 if (!branched())
1240 ++rootOffset;
1241 else if (treeLeafOffset() != treeLeafSize() - 1)
1242 ++treeLeafOffset();
1243 else
1244 treeIncrement();
1342 if (++path.leafOffset() == path.leafSize() && branched())
1343 path.moveRight(map->height);
12451344 return *this;
12461345 }
12471346
12541353
12551354 /// predecrement - move to the previous interval.
12561355 const_iterator &operator--() {
1257 if (!branched()) {
1258 assert(rootOffset && "Cannot decrement begin()");
1259 --rootOffset;
1260 } else if (valid() && treeLeafOffset())
1261 --treeLeafOffset();
1356 if (path.leafOffset() && (valid() || !branched()))
1357 --path.leafOffset();
12621358 else
1263 treeDecrement();
1359 path.moveLeft(map->height);
12641360 return *this;
12651361 }
12661362
12771373 if (branched())
12781374 treeFind(x);
12791375 else
1280 rootOffset = map->rootLeaf().findFrom(0, map->rootSize, x);
1376 setRoot(map->rootLeaf().findFrom(0, map->rootSize, x));
12811377 }
12821378
12831379 /// advanceTo - Move to the first interval with stop >= x, or end().
12871383 if (branched())
12881384 treeAdvanceTo(x);
12891385 else
1290 rootOffset = map->rootLeaf().findFrom(rootOffset, map->rootSize, x);
1386 path.leafOffset() =
1387 map->rootLeaf().findFrom(path.leafOffset(), map->rootSize, x);
12911388 }
12921389
12931390 };
1294
1295 // pathFillLeft - Complete path by following left-most branches.
1296 template
1297 void IntervalMap::
1298 const_iterator::pathFillLeft() {
1299 IntervalMapImpl::NodeRef NR = pathNextDown();
1300 for (unsigned i = map->height - path.size() - 1; i; --i) {
1301 path.push_back(PathEntry(NR, 0));
1302 NR = NR.subtree(0);
1303 }
1304 path.push_back(PathEntry(NR, 0));
1305 }
13061391
13071392 // pathFillFind - Complete path by searching for x.
13081393 template
13091394 void IntervalMap::
13101395 const_iterator::pathFillFind(KeyT x) {
1311 IntervalMapImpl::NodeRef NR = pathNextDown();
1312 for (unsigned i = map->height - path.size() - 1; i; --i) {
1396 IntervalMapImpl::NodeRef NR = path.subtree(path.height());
1397 for (unsigned i = map->height - path.height() - 1; i; --i) {
13131398 unsigned p = NR.get().safeFind(0, x);
1314 path.push_back(PathEntry(NR, p));
1399 path.push(NR, p);
13151400 NR = NR.subtree(p);
13161401 }
1317 path.push_back(PathEntry(NR, NR.get().safeFind(0, x)));
1318 }
1319
1320 // pathFillRight - Complete path by adding rightmost entries.
1321 template
1322 void IntervalMap::
1323 const_iterator::pathFillRight() {
1324 IntervalMapImpl::NodeRef NR = pathNextDown();
1325 for (unsigned i = map->height - path.size() - 1; i; --i) {
1326 unsigned p = NR.size() - 1;
1327 path.push_back(PathEntry(NR, p));
1328 NR = NR.subtree(p);
1329 }
1330 path.push_back(PathEntry(NR, NR.size() - 1));
1331 }
1332
1333 /// leftSibling - find the left sibling node to path[level].
1334 /// @param level 0 is just below the root, map->height - 1 for the leaves.
1335 /// @return The left sibling NodeRef, or NULL.
1336 template
1337 IntervalMapImpl::NodeRef IntervalMap::
1338 const_iterator::leftSibling(unsigned level) const {
1339 using namespace IntervalMapImpl;
1340 assert(branched() && "Not at a branched node");
1341 assert(level <= path.size() && "Bad level");
1342
1343 // Go up the tree until we can go left.
1344 unsigned h = level;
1345 while (h && pathOffset(h - 1) == 0)
1346 --h;
1347
1348 // We are at the first leaf node, no left sibling.
1349 if (!h && rootOffset == 0)
1350 return NodeRef();
1351
1352 // NR is the subtree containing our left sibling.
1353 NodeRef NR = h ?
1354 pathNode(h - 1).subtree(pathOffset(h - 1) - 1) :
1355 map->rootBranch().subtree(rootOffset - 1);
1356
1357 // Keep right all the way down.
1358 for (; h != level; ++h)
1359 NR = NR.subtree(NR.size() - 1);
1360 return NR;
1361 }
1362
1363 /// rightSibling - find the right sibling node to path[level].
1364 /// @param level 0 is just below the root, map->height - 1 for the leaves.
1365 /// @return The right sibling NodeRef, or NULL.
1366 template
1367 IntervalMapImpl::NodeRef IntervalMap::
1368 const_iterator::rightSibling(unsigned level) const {
1369 using namespace IntervalMapImpl;
1370 assert(branched() && "Not at a branched node");
1371 assert(level <= this->path.size() && "Bad level");
1372
1373 // Go up the tree until we can go right.
1374 unsigned h = level;
1375 while (h && pathOffset(h - 1) == pathNode(h - 1).size() - 1)
1376 --h;
1377
1378 // We are at the last leaf node, no right sibling.
1379 if (!h && rootOffset == map->rootSize - 1)
1380 return NodeRef();
1381
1382 // NR is the subtree containing our right sibling.
1383 NodeRef NR = h ?
1384 pathNode(h - 1).subtree(pathOffset(h - 1) + 1) :
1385 map->rootBranch().subtree(rootOffset + 1);
1386
1387 // Keep left all the way down.
1388 for (; h != level; ++h)
1389 NR = NR.subtree(0);
1390 return NR;
1391 }
1392
1393 // treeIncrement - Move to the beginning of the next leaf node.
1394 template
1395 void IntervalMap::
1396 const_iterator::treeIncrement() {
1397 assert(branched() && "treeIncrement is not for small maps");
1398 assert(path.size() == map->height && "inconsistent iterator");
1399 do path.pop_back();
1400 while (!path.empty() && path.back().second == path.back().first.size() - 1);
1401 if (path.empty()) {
1402 ++rootOffset;
1403 if (!valid())
1404 return;
1405 } else
1406 ++path.back().second;
1407 pathFillLeft();
1408 }
1409
1410 // treeDecrement - Move to the end of the previous leaf node.
1411 template
1412 void IntervalMap::
1413 const_iterator::treeDecrement() {
1414 assert(branched() && "treeDecrement is not for small maps");
1415 if (valid()) {
1416 assert(path.size() == map->height && "inconsistent iterator");
1417 do path.pop_back();
1418 while (!path.empty() && path.back().second == 0);
1419 }
1420 if (path.empty()) {
1421 assert(rootOffset && "cannot treeDecrement() on begin()");
1422 --rootOffset;
1423 } else
1424 --path.back().second;
1425 pathFillRight();
1402 path.push(NR, NR.get().safeFind(0, x));
14261403 }
14271404
14281405 // treeFind - Find in a branched tree.
14291406 template
14301407 void IntervalMap::
14311408 const_iterator::treeFind(KeyT x) {
1432 path.clear();
1433 rootOffset = map->rootBranch().findFrom(0, map->rootSize, x);
1409 setRoot(map->rootBranch().findFrom(0, map->rootSize, x));
14341410 if (valid())
14351411 pathFillFind(x);
14361412 }
14871463
14881464 explicit iterator(IntervalMap &map) : const_iterator(map) {}
14891465
1490 void setNodeSize(unsigned Level, unsigned Size);
14911466 void setNodeStop(unsigned Level, KeyT Stop);
14921467 bool insertNode(unsigned Level, IntervalMapImpl::NodeRef Node, KeyT Stop);
14931468 template bool overflow(unsigned Level);
14991474
15001475 };
15011476
1502 /// setNodeSize - Set the size of the node at path[level], updating both path
1503 /// and the real tree.
1504 /// @param level 0 is just below the root, map->height - 1 for the leaves.
1505 /// @param size New node size.
1506 template
1507 void IntervalMap::
1508 iterator::setNodeSize(unsigned Level, unsigned Size) {
1509 this->pathNode(Level).setSize(Size);
1510 if (Level)
1511 this->pathNode(Level-1).subtree(this->pathOffset(Level-1)).setSize(Size);
1512 else
1513 this->map->rootBranch().subtree(this->rootOffset).setSize(Size);
1514 }
1515
15161477 /// setNodeStop - Update the stop key of the current node at level and above.
15171478 template
15181479 void IntervalMap::
15191480 iterator::setNodeStop(unsigned Level, KeyT Stop) {
1520 while (Level--) {
1521 this->pathNode(Level).template get()
1522 .stop(this->pathOffset(Level)) = Stop;
1523 if (this->pathOffset(Level) != this->pathNode(Level).size() - 1)
1481 // There are no references to the root node, so nothing to update.
1482 if (!Level)
1483 return;
1484 IntervalMapImpl::Path &P = this->path;
1485 // Update nodes pointing to the current node.
1486 while (--Level) {
1487 P.node(Level).stop(P.offset(Level)) = Stop;
1488 if (!P.atLastBranch(Level))
15241489 return;
15251490 }
1526 this->map->rootBranch().stop(this->rootOffset) = Stop;
1491 // Update root separately since it has a different layout.
1492 P.node(Level).stop(P.offset(Level)) = Stop;
15271493 }
15281494
15291495 /// insertNode - insert a node before the current path at level.
15351501 template
15361502 bool IntervalMap::
15371503 iterator::insertNode(unsigned Level, IntervalMapImpl::NodeRef Node, KeyT Stop) {
1504 assert(Level && "Cannot insert next to the root");
15381505 bool SplitRoot = false;
1539
1540 if (!Level) {
1506 IntervalMap &IM = *this->map;
1507 IntervalMapImpl::Path &P = this->path;
1508
1509 if (Level == 1) {
15411510 // Insert into the root branch node.
1542 IntervalMap &IM = *this->map;
15431511 if (IM.rootSize < RootBranch::Capacity) {
1544 IM.rootBranch().insert(this->rootOffset, IM.rootSize, Node, Stop);
1545 ++IM.rootSize;
1512 IM.rootBranch().insert(P.offset(0), IM.rootSize, Node, Stop);
1513 P.setSize(0, ++IM.rootSize);
15461514 return SplitRoot;
15471515 }
15481516
15491517 // We need to split the root while keeping our position.
15501518 SplitRoot = true;
1551 IdxPair Offset = IM.splitRoot(this->rootOffset);
1552 this->rootOffset = Offset.first;
1553 this->path.insert(this->path.begin(),std::make_pair(
1554 this->map->rootBranch().subtree(Offset.first), Offset.second));
1555 Level = 1;
1519 IdxPair Offset = IM.splitRoot(P.offset(0));
1520 P.replaceRoot(&IM.rootBranch(), IM.rootSize, Offset);
1521
1522 // Fall through to insert at the new higher level.
1523 ++Level;
15561524 }
15571525
15581526 // When inserting before end(), make sure we have a valid path.
1559 if (!this->valid()) {
1560 this->treeDecrement();
1561 ++this->pathOffset(Level-1);
1562 }
1563
1564 // Insert into the branch node at level-1.
1565 if (this->pathNode(Level-1).size() == Branch::Capacity) {
1527 P.legalizeForInsert(--Level);
1528
1529 // Insert into the branch node at Level-1.
1530 if (P.size(Level) == Branch::Capacity) {
1531 // Branch node is full, handle handle the overflow.
15661532 assert(!SplitRoot && "Cannot overflow after splitting the root");
1567 SplitRoot = overflow(Level - 1);
1533 SplitRoot = overflow(Level);
15681534 Level += SplitRoot;
15691535 }
1570 IntervalMapImpl::NodeRef NR = this->pathNode(Level-1);
1571 unsigned Offset = this->pathOffset(Level-1);
1572 NR.get().insert(Offset, NR.size(), Node, Stop);
1573 setNodeSize(Level - 1, NR.size() + 1);
1536 P.node(Level).insert(P.offset(Level), P.size(Level), Node, Stop);
1537 P.setSize(Level, P.size(Level) + 1);
15741538 return SplitRoot;
15751539 }
15761540
15801544 iterator::insert(KeyT a, KeyT b, ValT y) {
15811545 if (this->branched())
15821546 return treeInsert(a, b, y);
1583 IdxPair IP = this->map->rootLeaf().insertFrom(this->rootOffset,
1584 this->map->rootSize,
1585 a, b, y);
1547 IntervalMap &IM = *this->map;
1548 IntervalMapImpl::Path &P = this->path;
1549
1550 // Try simple root leaf insert.
1551 IdxPair IP = IM.rootLeaf().insertFrom(P.leafOffset(), IM.rootSize, a, b, y);
1552
1553 // Was the root node insert successful?
15861554 if (IP.second <= RootLeaf::Capacity) {
1587 this->rootOffset = IP.first;
1588 this->map->rootSize = IP.second;
1555 P.leafOffset() = IP.first;
1556 P.setSize(0, IM.rootSize = IP.second);
15891557 return;
15901558 }
1591 IdxPair Offset = this->map->branchRoot(this->rootOffset);
1592 this->rootOffset = Offset.first;
1593 this->path.push_back(std::make_pair(
1594 this->map->rootBranch().subtree(Offset.first), Offset.second));
1559
1560 // Root leaf node is full, we must branch.
1561 IdxPair Offset = IM.branchRoot(P.leafOffset());
1562 P.replaceRoot(&IM.rootBranch(), IM.rootSize, Offset);
1563
1564 // Now it fits in the new leaf.
15951565 treeInsert(a, b, y);
15961566 }
15971567
15991569 template
16001570 void IntervalMap::
16011571 iterator::treeInsert(KeyT a, KeyT b, ValT y) {
1602 if (!this->valid()) {
1603 // end() has an empty path. Go back to the last leaf node and use an
1604 // invalid offset instead.
1605 this->treeDecrement();
1606 ++this->treeLeafOffset();
1607 }
1608 IdxPair IP = this->treeLeaf().insertFrom(this->treeLeafOffset(),
1609 this->treeLeafSize(), a, b, y);
1610 this->treeLeafOffset() = IP.first;
1611 if (IP.second <= Leaf::Capacity) {
1612 setNodeSize(this->map->height - 1, IP.second);
1613 if (IP.first == IP.second - 1)
1614 setNodeStop(this->map->height - 1, this->treeLeaf().stop(IP.first));
1615 return;
1616 }
1617 // Leaf node has no space.
1618 overflow(this->map->height - 1);
1619 IP = this->treeLeaf().insertFrom(this->treeLeafOffset(),
1620 this->treeLeafSize(), a, b, y);
1621 this->treeLeafOffset() = IP.first;
1622 setNodeSize(this->map->height-1, IP.second);
1572 IntervalMap &IM = *this->map;
1573 IntervalMapImpl::Path &P = this->path;
1574
1575 P.legalizeForInsert(IM.height);
1576 IdxPair IP = P.leaf().insertFrom(P.leafOffset(), P.leafSize(), a, b, y);
1577
1578 // Leaf insertion unsuccessful? Overflow and try again.
1579 if (IP.second > Leaf::Capacity) {
1580 overflow(IM.height);
1581 IP = P.leaf().insertFrom(P.leafOffset(), P.leafSize(), a, b, y);
1582 assert(IP.second <= Leaf::Capacity && "overflow() didn't make room");
1583 }
1584
1585 // Inserted, update offset and leaf size.
1586 P.leafOffset() = IP.first;
1587 P.setSize(IM.height, IP.second);
1588
1589 // Insert was the last node entry, update stops.
16231590 if (IP.first == IP.second - 1)
1624 setNodeStop(this->map->height - 1, this->treeLeaf().stop(IP.first));
1591 setNodeStop(IM.height, P.leaf().stop(IP.first));
16251592
16261593 // FIXME: Handle cross-node coalescing.
16271594 }
16371604 bool IntervalMap::
16381605 iterator::overflow(unsigned Level) {
16391606 using namespace IntervalMapImpl;
1607 Path &P = this->path;
16401608 unsigned CurSize[4];
16411609 NodeT *Node[4];
16421610 unsigned Nodes = 0;
16431611 unsigned Elements = 0;
1644 unsigned Offset = this->pathOffset(Level);
1612 unsigned Offset = P.offset(Level);
16451613
16461614 // Do we have a left sibling?
1647 NodeRef LeftSib = this->leftSibling(Level);
1615 NodeRef LeftSib = P.getLeftSibling(Level);
16481616 if (LeftSib) {
16491617 Offset += Elements = CurSize[Nodes] = LeftSib.size();
16501618 Node[Nodes++] = &LeftSib.get();
16511619 }
16521620
16531621 // Current node.
1654 NodeRef CurNode = this->pathNode(Level);
1655 Elements += CurSize[Nodes] = CurNode.size();
1656 Node[Nodes++] = &CurNode.get();
1622 Elements += CurSize[Nodes] = P.size(Level);
1623 Node[Nodes++] = &P.node(Level);
16571624
16581625 // Do we have a right sibling?
1659 NodeRef RightSib = this->rightSibling(Level);
1626 NodeRef RightSib = P.getRightSibling(Level);
16601627 if (RightSib) {
16611628 Offset += Elements = CurSize[Nodes] = RightSib.size();
16621629 Node[Nodes++] = &RightSib.get();
16811648
16821649 // Move current location to the leftmost node.
16831650 if (LeftSib)
1684 this->treeDecrement();
1651 P.moveLeft(Level);
16851652
16861653 // Move elements right.
16871654 for (int n = Nodes - 1; n; --n) {
17271694 SplitRoot = insertNode(Level, NodeRef(Node[Pos], NewSize[Pos]), Stop);
17281695 Level += SplitRoot;
17291696 } else {
1730 setNodeSize(Level, NewSize[Pos]);
1697 P.setSize(Level, NewSize[Pos]);
17311698 setNodeStop(Level, Stop);
17321699 }
17331700 if (Pos + 1 == Nodes)
17341701 break;
1735 this->treeIncrement();
1702 P.moveRight(Level);
17361703 ++Pos;
17371704 }
17381705
17391706 // Where was I? Find NewOffset.
17401707 while(Pos != NewOffset.first) {
1741 this->treeDecrement();
1708 P.moveLeft(Level);
17421709 --Pos;
17431710 }
1744 this->pathOffset(Level) = NewOffset.second;
1711 P.offset(Level) = NewOffset.second;
17451712 return SplitRoot;
17461713 }
17471714
1414
1515 namespace llvm {
1616 namespace IntervalMapImpl {
17
18 void Path::replaceRoot(void *Root, unsigned Size, IdxPair Offsets) {
19 assert(!path.empty() && "Can't replace missing root");
20 path.front() = Entry(Root, Size, Offsets.first);
21 path.insert(path.begin() + 1, Entry(subtree(0), Offsets.second));
22 }
23
24 NodeRef Path::getLeftSibling(unsigned Level) const {
25 // The root has no siblings.
26 if (Level == 0)
27 return NodeRef();
28
29 // Go up the tree until we can go left.
30 unsigned l = Level - 1;
31 while (l && path[l].offset == 0)
32 --l;
33
34 // We can't go left.
35 if (path[l].offset == 0)
36 return NodeRef();
37
38 // NR is the subtree containing our left sibling.
39 NodeRef NR = path[l].subtree(path[l].offset - 1);
40
41 // Keep right all the way down.
42 for (++l; l != Level; ++l)
43 NR = NR.subtree(NR.size() - 1);
44 return NR;
45 }
46
47 void Path::moveLeft(unsigned Level) {
48 assert(Level != 0 && "Cannot move the root node");
49
50 // Go up the tree until we can go left.
51 unsigned l = 0;
52 if (valid()) {
53 l = Level - 1;
54 while (path[l].offset == 0) {
55 assert(l != 0 && "Cannot move beyond begin()");
56 --l;
57 }
58 } else if (height() < Level)
59 // end() may have created a height=0 path.
60 path.resize(Level + 1, Entry(0, 0, 0));
61
62 // NR is the subtree containing our left sibling.
63 --path[l].offset;
64 NodeRef NR = subtree(l);
65
66 // Get the rightmost node in the subtree.
67 for (++l; l != Level; ++l) {
68 path[l] = Entry(NR, NR.size() - 1);
69 NR = NR.subtree(NR.size() - 1);
70 }
71 path[l] = Entry(NR, NR.size() - 1);
72 }
73
74 NodeRef Path::getRightSibling(unsigned Level) const {
75 // The root has no siblings.
76 if (Level == 0)
77 return NodeRef();
78
79 // Go up the tree until we can go right.
80 unsigned l = Level - 1;
81 while (l && atLastBranch(l))
82 --l;
83
84 // We can't go right.
85 if (atLastBranch(l))
86 return NodeRef();
87
88 // NR is the subtree containing our right sibling.
89 NodeRef NR = path[l].subtree(path[l].offset + 1);
90
91 // Keep left all the way down.
92 for (++l; l != Level; ++l)
93 NR = NR.subtree(0);
94 return NR;
95 }
96
97 void Path::moveRight(unsigned Level) {
98 assert(Level != 0 && "Cannot move the root node");
99
100 // Go up the tree until we can go right.
101 unsigned l = Level - 1;
102 while (l && atLastBranch(l))
103 --l;
104
105 // NR is the subtree containing our right sibling. If we hit end(), we have
106 // offset(0) == node(0).size().
107 if (++path[l].offset == path[l].size)
108 return;
109 NodeRef NR = subtree(l);
110
111 for (++l; l != Level; ++l) {
112 path[l] = Entry(NR, 0);
113 NR = NR.subtree(0);
114 }
115 path[l] = Entry(NR, 0);
116 }
117
17118
18119 IdxPair distribute(unsigned Nodes, unsigned Elements, unsigned Capacity,
19120 const unsigned *CurSize, unsigned NewSize[],
55156 }
56157
57158 } // namespace IntervalMapImpl
58 } // namespace llvm
159 } // namespace llvm
59160