xref: /freebsd/contrib/llvm-project/llvm/lib/Support/IntervalMap.cpp (revision e25152834cdf3b353892835a4f3b157e066a8ed4)
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