12754fe60SDimitry Andric //===- lib/Support/IntervalMap.cpp - A sorted interval map ----------------===//
22754fe60SDimitry Andric //
32754fe60SDimitry Andric // The LLVM Compiler Infrastructure
42754fe60SDimitry Andric //
52754fe60SDimitry Andric // This file is distributed under the University of Illinois Open Source
62754fe60SDimitry Andric // License. See LICENSE.TXT for details.
72754fe60SDimitry Andric //
82754fe60SDimitry Andric //===----------------------------------------------------------------------===//
92754fe60SDimitry Andric //
102754fe60SDimitry Andric // This file implements the few non-templated functions in IntervalMap.
112754fe60SDimitry Andric //
122754fe60SDimitry Andric //===----------------------------------------------------------------------===//
132754fe60SDimitry Andric
142754fe60SDimitry Andric #include "llvm/ADT/IntervalMap.h"
152754fe60SDimitry Andric
162754fe60SDimitry Andric namespace llvm {
172754fe60SDimitry Andric namespace IntervalMapImpl {
182754fe60SDimitry Andric
replaceRoot(void * Root,unsigned Size,IdxPair Offsets)192754fe60SDimitry Andric void Path::replaceRoot(void *Root, unsigned Size, IdxPair Offsets) {
202754fe60SDimitry Andric assert(!path.empty() && "Can't replace missing root");
212754fe60SDimitry Andric path.front() = Entry(Root, Size, Offsets.first);
222754fe60SDimitry Andric path.insert(path.begin() + 1, Entry(subtree(0), Offsets.second));
232754fe60SDimitry Andric }
242754fe60SDimitry Andric
getLeftSibling(unsigned Level) const252754fe60SDimitry Andric NodeRef Path::getLeftSibling(unsigned Level) const {
262754fe60SDimitry Andric // The root has no siblings.
272754fe60SDimitry Andric if (Level == 0)
282754fe60SDimitry Andric return NodeRef();
292754fe60SDimitry Andric
302754fe60SDimitry Andric // Go up the tree until we can go left.
312754fe60SDimitry Andric unsigned l = Level - 1;
322754fe60SDimitry Andric while (l && path[l].offset == 0)
332754fe60SDimitry Andric --l;
342754fe60SDimitry Andric
352754fe60SDimitry Andric // We can't go left.
362754fe60SDimitry Andric if (path[l].offset == 0)
372754fe60SDimitry Andric return NodeRef();
382754fe60SDimitry Andric
392754fe60SDimitry Andric // NR is the subtree containing our left sibling.
402754fe60SDimitry Andric NodeRef NR = path[l].subtree(path[l].offset - 1);
412754fe60SDimitry Andric
422754fe60SDimitry Andric // Keep right all the way down.
432754fe60SDimitry Andric for (++l; l != Level; ++l)
442754fe60SDimitry Andric NR = NR.subtree(NR.size() - 1);
452754fe60SDimitry Andric return NR;
462754fe60SDimitry Andric }
472754fe60SDimitry Andric
moveLeft(unsigned Level)482754fe60SDimitry Andric void Path::moveLeft(unsigned Level) {
492754fe60SDimitry Andric assert(Level != 0 && "Cannot move the root node");
502754fe60SDimitry Andric
512754fe60SDimitry Andric // Go up the tree until we can go left.
522754fe60SDimitry Andric unsigned l = 0;
532754fe60SDimitry Andric if (valid()) {
542754fe60SDimitry Andric l = Level - 1;
552754fe60SDimitry Andric while (path[l].offset == 0) {
562754fe60SDimitry Andric assert(l != 0 && "Cannot move beyond begin()");
572754fe60SDimitry Andric --l;
582754fe60SDimitry Andric }
592754fe60SDimitry Andric } else if (height() < Level)
602754fe60SDimitry Andric // end() may have created a height=0 path.
61*91bc56edSDimitry Andric path.resize(Level + 1, Entry(nullptr, 0, 0));
622754fe60SDimitry Andric
632754fe60SDimitry Andric // NR is the subtree containing our left sibling.
642754fe60SDimitry Andric --path[l].offset;
652754fe60SDimitry Andric NodeRef NR = subtree(l);
662754fe60SDimitry Andric
672754fe60SDimitry Andric // Get the rightmost node in the subtree.
682754fe60SDimitry Andric for (++l; l != Level; ++l) {
692754fe60SDimitry Andric path[l] = Entry(NR, NR.size() - 1);
702754fe60SDimitry Andric NR = NR.subtree(NR.size() - 1);
712754fe60SDimitry Andric }
722754fe60SDimitry Andric path[l] = Entry(NR, NR.size() - 1);
732754fe60SDimitry Andric }
742754fe60SDimitry Andric
getRightSibling(unsigned Level) const752754fe60SDimitry Andric NodeRef Path::getRightSibling(unsigned Level) const {
762754fe60SDimitry Andric // The root has no siblings.
772754fe60SDimitry Andric if (Level == 0)
782754fe60SDimitry Andric return NodeRef();
792754fe60SDimitry Andric
802754fe60SDimitry Andric // Go up the tree until we can go right.
812754fe60SDimitry Andric unsigned l = Level - 1;
822754fe60SDimitry Andric while (l && atLastEntry(l))
832754fe60SDimitry Andric --l;
842754fe60SDimitry Andric
852754fe60SDimitry Andric // We can't go right.
862754fe60SDimitry Andric if (atLastEntry(l))
872754fe60SDimitry Andric return NodeRef();
882754fe60SDimitry Andric
892754fe60SDimitry Andric // NR is the subtree containing our right sibling.
902754fe60SDimitry Andric NodeRef NR = path[l].subtree(path[l].offset + 1);
912754fe60SDimitry Andric
922754fe60SDimitry Andric // Keep left all the way down.
932754fe60SDimitry Andric for (++l; l != Level; ++l)
942754fe60SDimitry Andric NR = NR.subtree(0);
952754fe60SDimitry Andric return NR;
962754fe60SDimitry Andric }
972754fe60SDimitry Andric
moveRight(unsigned Level)982754fe60SDimitry Andric void Path::moveRight(unsigned Level) {
992754fe60SDimitry Andric assert(Level != 0 && "Cannot move the root node");
1002754fe60SDimitry Andric
1012754fe60SDimitry Andric // Go up the tree until we can go right.
1022754fe60SDimitry Andric unsigned l = Level - 1;
1032754fe60SDimitry Andric while (l && atLastEntry(l))
1042754fe60SDimitry Andric --l;
1052754fe60SDimitry Andric
1062754fe60SDimitry Andric // NR is the subtree containing our right sibling. If we hit end(), we have
1072754fe60SDimitry Andric // offset(0) == node(0).size().
1082754fe60SDimitry Andric if (++path[l].offset == path[l].size)
1092754fe60SDimitry Andric return;
1102754fe60SDimitry Andric NodeRef NR = subtree(l);
1112754fe60SDimitry Andric
1122754fe60SDimitry Andric for (++l; l != Level; ++l) {
1132754fe60SDimitry Andric path[l] = Entry(NR, 0);
1142754fe60SDimitry Andric NR = NR.subtree(0);
1152754fe60SDimitry Andric }
1162754fe60SDimitry Andric path[l] = Entry(NR, 0);
1172754fe60SDimitry Andric }
1182754fe60SDimitry Andric
1192754fe60SDimitry Andric
distribute(unsigned Nodes,unsigned Elements,unsigned Capacity,const unsigned * CurSize,unsigned NewSize[],unsigned Position,bool Grow)1202754fe60SDimitry Andric IdxPair distribute(unsigned Nodes, unsigned Elements, unsigned Capacity,
1212754fe60SDimitry Andric const unsigned *CurSize, unsigned NewSize[],
1222754fe60SDimitry Andric unsigned Position, bool Grow) {
1232754fe60SDimitry Andric assert(Elements + Grow <= Nodes * Capacity && "Not enough room for elements");
1242754fe60SDimitry Andric assert(Position <= Elements && "Invalid position");
1252754fe60SDimitry Andric if (!Nodes)
1262754fe60SDimitry Andric return IdxPair();
1272754fe60SDimitry Andric
1282754fe60SDimitry Andric // Trivial algorithm: left-leaning even distribution.
1292754fe60SDimitry Andric const unsigned PerNode = (Elements + Grow) / Nodes;
1302754fe60SDimitry Andric const unsigned Extra = (Elements + Grow) % Nodes;
1312754fe60SDimitry Andric IdxPair PosPair = IdxPair(Nodes, 0);
1322754fe60SDimitry Andric unsigned Sum = 0;
1332754fe60SDimitry Andric for (unsigned n = 0; n != Nodes; ++n) {
1342754fe60SDimitry Andric Sum += NewSize[n] = PerNode + (n < Extra);
1352754fe60SDimitry Andric if (PosPair.first == Nodes && Sum > Position)
1362754fe60SDimitry Andric PosPair = IdxPair(n, Position - (Sum - NewSize[n]));
1372754fe60SDimitry Andric }
1382754fe60SDimitry Andric assert(Sum == Elements + Grow && "Bad distribution sum");
1392754fe60SDimitry Andric
1402754fe60SDimitry Andric // Subtract the Grow element that was added.
1412754fe60SDimitry Andric if (Grow) {
1422754fe60SDimitry Andric assert(PosPair.first < Nodes && "Bad algebra");
1432754fe60SDimitry Andric assert(NewSize[PosPair.first] && "Too few elements to need Grow");
1442754fe60SDimitry Andric --NewSize[PosPair.first];
1452754fe60SDimitry Andric }
1462754fe60SDimitry Andric
1472754fe60SDimitry Andric #ifndef NDEBUG
1482754fe60SDimitry Andric Sum = 0;
1492754fe60SDimitry Andric for (unsigned n = 0; n != Nodes; ++n) {
1502754fe60SDimitry Andric assert(NewSize[n] <= Capacity && "Overallocated node");
1512754fe60SDimitry Andric Sum += NewSize[n];
1522754fe60SDimitry Andric }
1532754fe60SDimitry Andric assert(Sum == Elements && "Bad distribution sum");
1542754fe60SDimitry Andric #endif
1552754fe60SDimitry Andric
1562754fe60SDimitry Andric return PosPair;
1572754fe60SDimitry Andric }
1582754fe60SDimitry Andric
1592754fe60SDimitry Andric } // namespace IntervalMapImpl
1602754fe60SDimitry Andric } // namespace llvm
1612754fe60SDimitry Andric
162