10b57cec5SDimitry Andric //===- lib/Support/IntervalMap.cpp - A sorted interval map ----------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file implements the few non-templated functions in IntervalMap.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric
130b57cec5SDimitry Andric #include "llvm/ADT/IntervalMap.h"
14*5ffd83dbSDimitry Andric #include <cassert>
150b57cec5SDimitry Andric
160b57cec5SDimitry Andric namespace llvm {
170b57cec5SDimitry Andric namespace IntervalMapImpl {
180b57cec5SDimitry Andric
replaceRoot(void * Root,unsigned Size,IdxPair Offsets)190b57cec5SDimitry Andric void Path::replaceRoot(void *Root, unsigned Size, IdxPair Offsets) {
200b57cec5SDimitry Andric assert(!path.empty() && "Can't replace missing root");
210b57cec5SDimitry Andric path.front() = Entry(Root, Size, Offsets.first);
220b57cec5SDimitry Andric path.insert(path.begin() + 1, Entry(subtree(0), Offsets.second));
230b57cec5SDimitry Andric }
240b57cec5SDimitry Andric
getLeftSibling(unsigned Level) const250b57cec5SDimitry Andric NodeRef Path::getLeftSibling(unsigned Level) const {
260b57cec5SDimitry Andric // The root has no siblings.
270b57cec5SDimitry Andric if (Level == 0)
280b57cec5SDimitry Andric return NodeRef();
290b57cec5SDimitry Andric
300b57cec5SDimitry Andric // Go up the tree until we can go left.
310b57cec5SDimitry Andric unsigned l = Level - 1;
320b57cec5SDimitry Andric while (l && path[l].offset == 0)
330b57cec5SDimitry Andric --l;
340b57cec5SDimitry Andric
350b57cec5SDimitry Andric // We can't go left.
360b57cec5SDimitry Andric if (path[l].offset == 0)
370b57cec5SDimitry Andric return NodeRef();
380b57cec5SDimitry Andric
390b57cec5SDimitry Andric // NR is the subtree containing our left sibling.
400b57cec5SDimitry Andric NodeRef NR = path[l].subtree(path[l].offset - 1);
410b57cec5SDimitry Andric
420b57cec5SDimitry Andric // Keep right all the way down.
430b57cec5SDimitry Andric for (++l; l != Level; ++l)
440b57cec5SDimitry Andric NR = NR.subtree(NR.size() - 1);
450b57cec5SDimitry Andric return NR;
460b57cec5SDimitry Andric }
470b57cec5SDimitry Andric
moveLeft(unsigned Level)480b57cec5SDimitry Andric void Path::moveLeft(unsigned Level) {
490b57cec5SDimitry Andric assert(Level != 0 && "Cannot move the root node");
500b57cec5SDimitry Andric
510b57cec5SDimitry Andric // Go up the tree until we can go left.
520b57cec5SDimitry Andric unsigned l = 0;
530b57cec5SDimitry Andric if (valid()) {
540b57cec5SDimitry Andric l = Level - 1;
550b57cec5SDimitry Andric while (path[l].offset == 0) {
560b57cec5SDimitry Andric assert(l != 0 && "Cannot move beyond begin()");
570b57cec5SDimitry Andric --l;
580b57cec5SDimitry Andric }
590b57cec5SDimitry Andric } else if (height() < Level)
600b57cec5SDimitry Andric // end() may have created a height=0 path.
610b57cec5SDimitry Andric path.resize(Level + 1, Entry(nullptr, 0, 0));
620b57cec5SDimitry Andric
630b57cec5SDimitry Andric // NR is the subtree containing our left sibling.
640b57cec5SDimitry Andric --path[l].offset;
650b57cec5SDimitry Andric NodeRef NR = subtree(l);
660b57cec5SDimitry Andric
670b57cec5SDimitry Andric // Get the rightmost node in the subtree.
680b57cec5SDimitry Andric for (++l; l != Level; ++l) {
690b57cec5SDimitry Andric path[l] = Entry(NR, NR.size() - 1);
700b57cec5SDimitry Andric NR = NR.subtree(NR.size() - 1);
710b57cec5SDimitry Andric }
720b57cec5SDimitry Andric path[l] = Entry(NR, NR.size() - 1);
730b57cec5SDimitry Andric }
740b57cec5SDimitry Andric
getRightSibling(unsigned Level) const750b57cec5SDimitry Andric NodeRef Path::getRightSibling(unsigned Level) const {
760b57cec5SDimitry Andric // The root has no siblings.
770b57cec5SDimitry Andric if (Level == 0)
780b57cec5SDimitry Andric return NodeRef();
790b57cec5SDimitry Andric
800b57cec5SDimitry Andric // Go up the tree until we can go right.
810b57cec5SDimitry Andric unsigned l = Level - 1;
820b57cec5SDimitry Andric while (l && atLastEntry(l))
830b57cec5SDimitry Andric --l;
840b57cec5SDimitry Andric
850b57cec5SDimitry Andric // We can't go right.
860b57cec5SDimitry Andric if (atLastEntry(l))
870b57cec5SDimitry Andric return NodeRef();
880b57cec5SDimitry Andric
890b57cec5SDimitry Andric // NR is the subtree containing our right sibling.
900b57cec5SDimitry Andric NodeRef NR = path[l].subtree(path[l].offset + 1);
910b57cec5SDimitry Andric
920b57cec5SDimitry Andric // Keep left all the way down.
930b57cec5SDimitry Andric for (++l; l != Level; ++l)
940b57cec5SDimitry Andric NR = NR.subtree(0);
950b57cec5SDimitry Andric return NR;
960b57cec5SDimitry Andric }
970b57cec5SDimitry Andric
moveRight(unsigned Level)980b57cec5SDimitry Andric void Path::moveRight(unsigned Level) {
990b57cec5SDimitry Andric assert(Level != 0 && "Cannot move the root node");
1000b57cec5SDimitry Andric
1010b57cec5SDimitry Andric // Go up the tree until we can go right.
1020b57cec5SDimitry Andric unsigned l = Level - 1;
1030b57cec5SDimitry Andric while (l && atLastEntry(l))
1040b57cec5SDimitry Andric --l;
1050b57cec5SDimitry Andric
1060b57cec5SDimitry Andric // NR is the subtree containing our right sibling. If we hit end(), we have
1070b57cec5SDimitry Andric // offset(0) == node(0).size().
1080b57cec5SDimitry Andric if (++path[l].offset == path[l].size)
1090b57cec5SDimitry Andric return;
1100b57cec5SDimitry Andric NodeRef NR = subtree(l);
1110b57cec5SDimitry Andric
1120b57cec5SDimitry Andric for (++l; l != Level; ++l) {
1130b57cec5SDimitry Andric path[l] = Entry(NR, 0);
1140b57cec5SDimitry Andric NR = NR.subtree(0);
1150b57cec5SDimitry Andric }
1160b57cec5SDimitry Andric path[l] = Entry(NR, 0);
1170b57cec5SDimitry Andric }
1180b57cec5SDimitry Andric
1190b57cec5SDimitry Andric
distribute(unsigned Nodes,unsigned Elements,unsigned Capacity,const unsigned * CurSize,unsigned NewSize[],unsigned Position,bool Grow)1200b57cec5SDimitry Andric IdxPair distribute(unsigned Nodes, unsigned Elements, unsigned Capacity,
1210b57cec5SDimitry Andric const unsigned *CurSize, unsigned NewSize[],
1220b57cec5SDimitry Andric unsigned Position, bool Grow) {
1230b57cec5SDimitry Andric assert(Elements + Grow <= Nodes * Capacity && "Not enough room for elements");
1240b57cec5SDimitry Andric assert(Position <= Elements && "Invalid position");
1250b57cec5SDimitry Andric if (!Nodes)
1260b57cec5SDimitry Andric return IdxPair();
1270b57cec5SDimitry Andric
1280b57cec5SDimitry Andric // Trivial algorithm: left-leaning even distribution.
1290b57cec5SDimitry Andric const unsigned PerNode = (Elements + Grow) / Nodes;
1300b57cec5SDimitry Andric const unsigned Extra = (Elements + Grow) % Nodes;
1310b57cec5SDimitry Andric IdxPair PosPair = IdxPair(Nodes, 0);
1320b57cec5SDimitry Andric unsigned Sum = 0;
1330b57cec5SDimitry Andric for (unsigned n = 0; n != Nodes; ++n) {
1340b57cec5SDimitry Andric Sum += NewSize[n] = PerNode + (n < Extra);
1350b57cec5SDimitry Andric if (PosPair.first == Nodes && Sum > Position)
1360b57cec5SDimitry Andric PosPair = IdxPair(n, Position - (Sum - NewSize[n]));
1370b57cec5SDimitry Andric }
1380b57cec5SDimitry Andric assert(Sum == Elements + Grow && "Bad distribution sum");
1390b57cec5SDimitry Andric
1400b57cec5SDimitry Andric // Subtract the Grow element that was added.
1410b57cec5SDimitry Andric if (Grow) {
1420b57cec5SDimitry Andric assert(PosPair.first < Nodes && "Bad algebra");
1430b57cec5SDimitry Andric assert(NewSize[PosPair.first] && "Too few elements to need Grow");
1440b57cec5SDimitry Andric --NewSize[PosPair.first];
1450b57cec5SDimitry Andric }
1460b57cec5SDimitry Andric
1470b57cec5SDimitry Andric #ifndef NDEBUG
1480b57cec5SDimitry Andric Sum = 0;
1490b57cec5SDimitry Andric for (unsigned n = 0; n != Nodes; ++n) {
1500b57cec5SDimitry Andric assert(NewSize[n] <= Capacity && "Overallocated node");
1510b57cec5SDimitry Andric Sum += NewSize[n];
1520b57cec5SDimitry Andric }
1530b57cec5SDimitry Andric assert(Sum == Elements && "Bad distribution sum");
1540b57cec5SDimitry Andric #endif
1550b57cec5SDimitry Andric
1560b57cec5SDimitry Andric return PosPair;
1570b57cec5SDimitry Andric }
1580b57cec5SDimitry Andric
1590b57cec5SDimitry Andric } // namespace IntervalMapImpl
1600b57cec5SDimitry Andric } // namespace llvm
1610b57cec5SDimitry Andric
162