xref: /src/contrib/llvm-project/llvm/lib/Support/IntervalMap.cpp (revision 5ffd83dbcc34f10e07f6d3e968ae6365869615f4)
1cf099d11SDimitry Andric //===- lib/Support/IntervalMap.cpp - A sorted interval map ----------------===//
2cf099d11SDimitry Andric //
3e6d15924SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e6d15924SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e6d15924SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6cf099d11SDimitry Andric //
7cf099d11SDimitry Andric //===----------------------------------------------------------------------===//
8cf099d11SDimitry Andric //
9cf099d11SDimitry Andric // This file implements the few non-templated functions in IntervalMap.
10cf099d11SDimitry Andric //
11cf099d11SDimitry Andric //===----------------------------------------------------------------------===//
12cf099d11SDimitry Andric 
13cf099d11SDimitry Andric #include "llvm/ADT/IntervalMap.h"
14cfca06d7SDimitry Andric #include <cassert>
15cf099d11SDimitry Andric 
16cf099d11SDimitry Andric namespace llvm {
17cf099d11SDimitry Andric namespace IntervalMapImpl {
18cf099d11SDimitry Andric 
replaceRoot(void * Root,unsigned Size,IdxPair Offsets)19cf099d11SDimitry Andric void Path::replaceRoot(void *Root, unsigned Size, IdxPair Offsets) {
20cf099d11SDimitry Andric   assert(!path.empty() && "Can't replace missing root");
21cf099d11SDimitry Andric   path.front() = Entry(Root, Size, Offsets.first);
22cf099d11SDimitry Andric   path.insert(path.begin() + 1, Entry(subtree(0), Offsets.second));
23cf099d11SDimitry Andric }
24cf099d11SDimitry Andric 
getLeftSibling(unsigned Level) const25cf099d11SDimitry Andric NodeRef Path::getLeftSibling(unsigned Level) const {
26cf099d11SDimitry Andric   // The root has no siblings.
27cf099d11SDimitry Andric   if (Level == 0)
28cf099d11SDimitry Andric     return NodeRef();
29cf099d11SDimitry Andric 
30cf099d11SDimitry Andric   // Go up the tree until we can go left.
31cf099d11SDimitry Andric   unsigned l = Level - 1;
32cf099d11SDimitry Andric   while (l && path[l].offset == 0)
33cf099d11SDimitry Andric     --l;
34cf099d11SDimitry Andric 
35cf099d11SDimitry Andric   // We can't go left.
36cf099d11SDimitry Andric   if (path[l].offset == 0)
37cf099d11SDimitry Andric     return NodeRef();
38cf099d11SDimitry Andric 
39cf099d11SDimitry Andric   // NR is the subtree containing our left sibling.
40cf099d11SDimitry Andric   NodeRef NR = path[l].subtree(path[l].offset - 1);
41cf099d11SDimitry Andric 
42cf099d11SDimitry Andric   // Keep right all the way down.
43cf099d11SDimitry Andric   for (++l; l != Level; ++l)
44cf099d11SDimitry Andric     NR = NR.subtree(NR.size() - 1);
45cf099d11SDimitry Andric   return NR;
46cf099d11SDimitry Andric }
47cf099d11SDimitry Andric 
moveLeft(unsigned Level)48cf099d11SDimitry Andric void Path::moveLeft(unsigned Level) {
49cf099d11SDimitry Andric   assert(Level != 0 && "Cannot move the root node");
50cf099d11SDimitry Andric 
51cf099d11SDimitry Andric   // Go up the tree until we can go left.
52cf099d11SDimitry Andric   unsigned l = 0;
53cf099d11SDimitry Andric   if (valid()) {
54cf099d11SDimitry Andric     l = Level - 1;
55cf099d11SDimitry Andric     while (path[l].offset == 0) {
56cf099d11SDimitry Andric       assert(l != 0 && "Cannot move beyond begin()");
57cf099d11SDimitry Andric       --l;
58cf099d11SDimitry Andric     }
59cf099d11SDimitry Andric   } else if (height() < Level)
60cf099d11SDimitry Andric     // end() may have created a height=0 path.
615ca98fd9SDimitry Andric     path.resize(Level + 1, Entry(nullptr, 0, 0));
62cf099d11SDimitry Andric 
63cf099d11SDimitry Andric   // NR is the subtree containing our left sibling.
64cf099d11SDimitry Andric   --path[l].offset;
65cf099d11SDimitry Andric   NodeRef NR = subtree(l);
66cf099d11SDimitry Andric 
67cf099d11SDimitry Andric   // Get the rightmost node in the subtree.
68cf099d11SDimitry Andric   for (++l; l != Level; ++l) {
69cf099d11SDimitry Andric     path[l] = Entry(NR, NR.size() - 1);
70cf099d11SDimitry Andric     NR = NR.subtree(NR.size() - 1);
71cf099d11SDimitry Andric   }
72cf099d11SDimitry Andric   path[l] = Entry(NR, NR.size() - 1);
73cf099d11SDimitry Andric }
74cf099d11SDimitry Andric 
getRightSibling(unsigned Level) const75cf099d11SDimitry Andric NodeRef Path::getRightSibling(unsigned Level) const {
76cf099d11SDimitry Andric   // The root has no siblings.
77cf099d11SDimitry Andric   if (Level == 0)
78cf099d11SDimitry Andric     return NodeRef();
79cf099d11SDimitry Andric 
80cf099d11SDimitry Andric   // Go up the tree until we can go right.
81cf099d11SDimitry Andric   unsigned l = Level - 1;
82cf099d11SDimitry Andric   while (l && atLastEntry(l))
83cf099d11SDimitry Andric     --l;
84cf099d11SDimitry Andric 
85cf099d11SDimitry Andric   // We can't go right.
86cf099d11SDimitry Andric   if (atLastEntry(l))
87cf099d11SDimitry Andric     return NodeRef();
88cf099d11SDimitry Andric 
89cf099d11SDimitry Andric   // NR is the subtree containing our right sibling.
90cf099d11SDimitry Andric   NodeRef NR = path[l].subtree(path[l].offset + 1);
91cf099d11SDimitry Andric 
92cf099d11SDimitry Andric   // Keep left all the way down.
93cf099d11SDimitry Andric   for (++l; l != Level; ++l)
94cf099d11SDimitry Andric     NR = NR.subtree(0);
95cf099d11SDimitry Andric   return NR;
96cf099d11SDimitry Andric }
97cf099d11SDimitry Andric 
moveRight(unsigned Level)98cf099d11SDimitry Andric void Path::moveRight(unsigned Level) {
99cf099d11SDimitry Andric   assert(Level != 0 && "Cannot move the root node");
100cf099d11SDimitry Andric 
101cf099d11SDimitry Andric   // Go up the tree until we can go right.
102cf099d11SDimitry Andric   unsigned l = Level - 1;
103cf099d11SDimitry Andric   while (l && atLastEntry(l))
104cf099d11SDimitry Andric     --l;
105cf099d11SDimitry Andric 
106cf099d11SDimitry Andric   // NR is the subtree containing our right sibling. If we hit end(), we have
107cf099d11SDimitry Andric   // offset(0) == node(0).size().
108cf099d11SDimitry Andric   if (++path[l].offset == path[l].size)
109cf099d11SDimitry Andric     return;
110cf099d11SDimitry Andric   NodeRef NR = subtree(l);
111cf099d11SDimitry Andric 
112cf099d11SDimitry Andric   for (++l; l != Level; ++l) {
113cf099d11SDimitry Andric     path[l] = Entry(NR, 0);
114cf099d11SDimitry Andric     NR = NR.subtree(0);
115cf099d11SDimitry Andric   }
116cf099d11SDimitry Andric   path[l] = Entry(NR, 0);
117cf099d11SDimitry Andric }
118cf099d11SDimitry Andric 
119cf099d11SDimitry Andric 
distribute(unsigned Nodes,unsigned Elements,unsigned Capacity,const unsigned * CurSize,unsigned NewSize[],unsigned Position,bool Grow)120cf099d11SDimitry Andric IdxPair distribute(unsigned Nodes, unsigned Elements, unsigned Capacity,
121cf099d11SDimitry Andric                    const unsigned *CurSize, unsigned NewSize[],
122cf099d11SDimitry Andric                    unsigned Position, bool Grow) {
123cf099d11SDimitry Andric   assert(Elements + Grow <= Nodes * Capacity && "Not enough room for elements");
124cf099d11SDimitry Andric   assert(Position <= Elements && "Invalid position");
125cf099d11SDimitry Andric   if (!Nodes)
126cf099d11SDimitry Andric     return IdxPair();
127cf099d11SDimitry Andric 
128cf099d11SDimitry Andric   // Trivial algorithm: left-leaning even distribution.
129cf099d11SDimitry Andric   const unsigned PerNode = (Elements + Grow) / Nodes;
130cf099d11SDimitry Andric   const unsigned Extra = (Elements + Grow) % Nodes;
131cf099d11SDimitry Andric   IdxPair PosPair = IdxPair(Nodes, 0);
132cf099d11SDimitry Andric   unsigned Sum = 0;
133cf099d11SDimitry Andric   for (unsigned n = 0; n != Nodes; ++n) {
134cf099d11SDimitry Andric     Sum += NewSize[n] = PerNode + (n < Extra);
135cf099d11SDimitry Andric     if (PosPair.first == Nodes && Sum > Position)
136cf099d11SDimitry Andric       PosPair = IdxPair(n, Position - (Sum - NewSize[n]));
137cf099d11SDimitry Andric   }
138cf099d11SDimitry Andric   assert(Sum == Elements + Grow && "Bad distribution sum");
139cf099d11SDimitry Andric 
140cf099d11SDimitry Andric   // Subtract the Grow element that was added.
141cf099d11SDimitry Andric   if (Grow) {
142cf099d11SDimitry Andric     assert(PosPair.first < Nodes && "Bad algebra");
143cf099d11SDimitry Andric     assert(NewSize[PosPair.first] && "Too few elements to need Grow");
144cf099d11SDimitry Andric     --NewSize[PosPair.first];
145cf099d11SDimitry Andric   }
146cf099d11SDimitry Andric 
147cf099d11SDimitry Andric #ifndef NDEBUG
148cf099d11SDimitry Andric   Sum = 0;
149cf099d11SDimitry Andric   for (unsigned n = 0; n != Nodes; ++n) {
150cf099d11SDimitry Andric     assert(NewSize[n] <= Capacity && "Overallocated node");
151cf099d11SDimitry Andric     Sum += NewSize[n];
152cf099d11SDimitry Andric   }
153cf099d11SDimitry Andric   assert(Sum == Elements && "Bad distribution sum");
154cf099d11SDimitry Andric #endif
155cf099d11SDimitry Andric 
156cf099d11SDimitry Andric   return PosPair;
157cf099d11SDimitry Andric }
158cf099d11SDimitry Andric 
159cf099d11SDimitry Andric } // namespace IntervalMapImpl
160cf099d11SDimitry Andric } // namespace llvm
161cf099d11SDimitry Andric 
162