| //===- lib/Support/IntervalMap.cpp - A sorted interval map ----------------===// | |
| // | |
| // The LLVM Compiler Infrastructure | |
| // | |
| // This file is distributed under the University of Illinois Open Source | |
| // License. See LICENSE.TXT for details. | |
| // | |
| //===----------------------------------------------------------------------===// | |
| // | |
| // This file implements the few non-templated functions in IntervalMap. | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #include "llvm/ADT/IntervalMap.h" | |
| namespace llvm { | |
| namespace IntervalMapImpl { | |
| void Path::replaceRoot(void *Root, unsigned Size, IdxPair Offsets) { | |
| assert(!path.empty() && "Can't replace missing root"); | |
| path.front() = Entry(Root, Size, Offsets.first); | |
| path.insert(path.begin() + 1, Entry(subtree(0), Offsets.second)); | |
| } | |
| NodeRef Path::getLeftSibling(unsigned Level) const { | |
| // The root has no siblings. | |
| if (Level == 0) | |
| return NodeRef(); | |
| // Go up the tree until we can go left. | |
| unsigned l = Level - 1; | |
| while (l && path[l].offset == 0) | |
| --l; | |
| // We can't go left. | |
| if (path[l].offset == 0) | |
| return NodeRef(); | |
| // NR is the subtree containing our left sibling. | |
| NodeRef NR = path[l].subtree(path[l].offset - 1); | |
| // Keep right all the way down. | |
| for (++l; l != Level; ++l) | |
| NR = NR.subtree(NR.size() - 1); | |
| return NR; | |
| } | |
| void Path::moveLeft(unsigned Level) { | |
| assert(Level != 0 && "Cannot move the root node"); | |
| // Go up the tree until we can go left. | |
| unsigned l = 0; | |
| if (valid()) { | |
| l = Level - 1; | |
| while (path[l].offset == 0) { | |
| assert(l != 0 && "Cannot move beyond begin()"); | |
| --l; | |
| } | |
| } else if (height() < Level) | |
| // end() may have created a height=0 path. | |
| path.resize(Level + 1, Entry(nullptr, 0, 0)); | |
| // NR is the subtree containing our left sibling. | |
| --path[l].offset; | |
| NodeRef NR = subtree(l); | |
| // Get the rightmost node in the subtree. | |
| for (++l; l != Level; ++l) { | |
| path[l] = Entry(NR, NR.size() - 1); | |
| NR = NR.subtree(NR.size() - 1); | |
| } | |
| path[l] = Entry(NR, NR.size() - 1); | |
| } | |
| NodeRef Path::getRightSibling(unsigned Level) const { | |
| // The root has no siblings. | |
| if (Level == 0) | |
| return NodeRef(); | |
| // Go up the tree until we can go right. | |
| unsigned l = Level - 1; | |
| while (l && atLastEntry(l)) | |
| --l; | |
| // We can't go right. | |
| if (atLastEntry(l)) | |
| return NodeRef(); | |
| // NR is the subtree containing our right sibling. | |
| NodeRef NR = path[l].subtree(path[l].offset + 1); | |
| // Keep left all the way down. | |
| for (++l; l != Level; ++l) | |
| NR = NR.subtree(0); | |
| return NR; | |
| } | |
| void Path::moveRight(unsigned Level) { | |
| assert(Level != 0 && "Cannot move the root node"); | |
| // Go up the tree until we can go right. | |
| unsigned l = Level - 1; | |
| while (l && atLastEntry(l)) | |
| --l; | |
| // NR is the subtree containing our right sibling. If we hit end(), we have | |
| // offset(0) == node(0).size(). | |
| if (++path[l].offset == path[l].size) | |
| return; | |
| NodeRef NR = subtree(l); | |
| for (++l; l != Level; ++l) { | |
| path[l] = Entry(NR, 0); | |
| NR = NR.subtree(0); | |
| } | |
| path[l] = Entry(NR, 0); | |
| } | |
| IdxPair distribute(unsigned Nodes, unsigned Elements, unsigned Capacity, | |
| const unsigned *CurSize, unsigned NewSize[], | |
| unsigned Position, bool Grow) { | |
| assert(Elements + Grow <= Nodes * Capacity && "Not enough room for elements"); | |
| assert(Position <= Elements && "Invalid position"); | |
| if (!Nodes) | |
| return IdxPair(); | |
| // Trivial algorithm: left-leaning even distribution. | |
| const unsigned PerNode = (Elements + Grow) / Nodes; | |
| const unsigned Extra = (Elements + Grow) % Nodes; | |
| IdxPair PosPair = IdxPair(Nodes, 0); | |
| unsigned Sum = 0; | |
| for (unsigned n = 0; n != Nodes; ++n) { | |
| Sum += NewSize[n] = PerNode + (n < Extra); | |
| if (PosPair.first == Nodes && Sum > Position) | |
| PosPair = IdxPair(n, Position - (Sum - NewSize[n])); | |
| } | |
| assert(Sum == Elements + Grow && "Bad distribution sum"); | |
| // Subtract the Grow element that was added. | |
| if (Grow) { | |
| assert(PosPair.first < Nodes && "Bad algebra"); | |
| assert(NewSize[PosPair.first] && "Too few elements to need Grow"); | |
| --NewSize[PosPair.first]; | |
| } | |
| #ifndef NDEBUG | |
| Sum = 0; | |
| for (unsigned n = 0; n != Nodes; ++n) { | |
| assert(NewSize[n] <= Capacity && "Overallocated node"); | |
| Sum += NewSize[n]; | |
| } | |
| assert(Sum == Elements && "Bad distribution sum"); | |
| #endif | |
| return PosPair; | |
| } | |
| } // namespace IntervalMapImpl | |
| } // namespace llvm | |