diff options
Diffstat (limited to 'contrib/llvm/lib/Support/IntervalMap.cpp')
-rw-r--r-- | contrib/llvm/lib/Support/IntervalMap.cpp | 161 |
1 files changed, 161 insertions, 0 deletions
diff --git a/contrib/llvm/lib/Support/IntervalMap.cpp b/contrib/llvm/lib/Support/IntervalMap.cpp new file mode 100644 index 0000000..4dfcc40 --- /dev/null +++ b/contrib/llvm/lib/Support/IntervalMap.cpp @@ -0,0 +1,161 @@ +//===- 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(0, 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 + |