1345945e3SJakob Stoklund Olesen //===- lib/Support/IntervalMap.cpp - A sorted interval map ----------------===//
2345945e3SJakob Stoklund Olesen //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6345945e3SJakob Stoklund Olesen //
7345945e3SJakob Stoklund Olesen //===----------------------------------------------------------------------===//
8345945e3SJakob Stoklund Olesen //
9345945e3SJakob Stoklund Olesen // This file implements the few non-templated functions in IntervalMap.
10345945e3SJakob Stoklund Olesen //
11345945e3SJakob Stoklund Olesen //===----------------------------------------------------------------------===//
12345945e3SJakob Stoklund Olesen
13345945e3SJakob Stoklund Olesen #include "llvm/ADT/IntervalMap.h"
14*eb812efaSJoerg Sonnenberger #include <cassert>
15345945e3SJakob Stoklund Olesen
16345945e3SJakob Stoklund Olesen namespace llvm {
17345945e3SJakob Stoklund Olesen namespace IntervalMapImpl {
18345945e3SJakob Stoklund Olesen
replaceRoot(void * Root,unsigned Size,IdxPair Offsets)19a12095d2SJakob Stoklund Olesen void Path::replaceRoot(void *Root, unsigned Size, IdxPair Offsets) {
20a12095d2SJakob Stoklund Olesen assert(!path.empty() && "Can't replace missing root");
21a12095d2SJakob Stoklund Olesen path.front() = Entry(Root, Size, Offsets.first);
22a12095d2SJakob Stoklund Olesen path.insert(path.begin() + 1, Entry(subtree(0), Offsets.second));
23a12095d2SJakob Stoklund Olesen }
24a12095d2SJakob Stoklund Olesen
getLeftSibling(unsigned Level) const25a12095d2SJakob Stoklund Olesen NodeRef Path::getLeftSibling(unsigned Level) const {
26a12095d2SJakob Stoklund Olesen // The root has no siblings.
27a12095d2SJakob Stoklund Olesen if (Level == 0)
28a12095d2SJakob Stoklund Olesen return NodeRef();
29a12095d2SJakob Stoklund Olesen
30a12095d2SJakob Stoklund Olesen // Go up the tree until we can go left.
31a12095d2SJakob Stoklund Olesen unsigned l = Level - 1;
32a12095d2SJakob Stoklund Olesen while (l && path[l].offset == 0)
33a12095d2SJakob Stoklund Olesen --l;
34a12095d2SJakob Stoklund Olesen
35a12095d2SJakob Stoklund Olesen // We can't go left.
36a12095d2SJakob Stoklund Olesen if (path[l].offset == 0)
37a12095d2SJakob Stoklund Olesen return NodeRef();
38a12095d2SJakob Stoklund Olesen
39a12095d2SJakob Stoklund Olesen // NR is the subtree containing our left sibling.
40a12095d2SJakob Stoklund Olesen NodeRef NR = path[l].subtree(path[l].offset - 1);
41a12095d2SJakob Stoklund Olesen
42a12095d2SJakob Stoklund Olesen // Keep right all the way down.
43a12095d2SJakob Stoklund Olesen for (++l; l != Level; ++l)
44a12095d2SJakob Stoklund Olesen NR = NR.subtree(NR.size() - 1);
45a12095d2SJakob Stoklund Olesen return NR;
46a12095d2SJakob Stoklund Olesen }
47a12095d2SJakob Stoklund Olesen
moveLeft(unsigned Level)48a12095d2SJakob Stoklund Olesen void Path::moveLeft(unsigned Level) {
49a12095d2SJakob Stoklund Olesen assert(Level != 0 && "Cannot move the root node");
50a12095d2SJakob Stoklund Olesen
51a12095d2SJakob Stoklund Olesen // Go up the tree until we can go left.
52a12095d2SJakob Stoklund Olesen unsigned l = 0;
53a12095d2SJakob Stoklund Olesen if (valid()) {
54a12095d2SJakob Stoklund Olesen l = Level - 1;
55a12095d2SJakob Stoklund Olesen while (path[l].offset == 0) {
56a12095d2SJakob Stoklund Olesen assert(l != 0 && "Cannot move beyond begin()");
57a12095d2SJakob Stoklund Olesen --l;
58a12095d2SJakob Stoklund Olesen }
59a12095d2SJakob Stoklund Olesen } else if (height() < Level)
60a12095d2SJakob Stoklund Olesen // end() may have created a height=0 path.
61c10719f5SCraig Topper path.resize(Level + 1, Entry(nullptr, 0, 0));
62a12095d2SJakob Stoklund Olesen
63a12095d2SJakob Stoklund Olesen // NR is the subtree containing our left sibling.
64a12095d2SJakob Stoklund Olesen --path[l].offset;
65a12095d2SJakob Stoklund Olesen NodeRef NR = subtree(l);
66a12095d2SJakob Stoklund Olesen
67a12095d2SJakob Stoklund Olesen // Get the rightmost node in the subtree.
68a12095d2SJakob Stoklund Olesen for (++l; l != Level; ++l) {
69a12095d2SJakob Stoklund Olesen path[l] = Entry(NR, NR.size() - 1);
70a12095d2SJakob Stoklund Olesen NR = NR.subtree(NR.size() - 1);
71a12095d2SJakob Stoklund Olesen }
72a12095d2SJakob Stoklund Olesen path[l] = Entry(NR, NR.size() - 1);
73a12095d2SJakob Stoklund Olesen }
74a12095d2SJakob Stoklund Olesen
getRightSibling(unsigned Level) const75a12095d2SJakob Stoklund Olesen NodeRef Path::getRightSibling(unsigned Level) const {
76a12095d2SJakob Stoklund Olesen // The root has no siblings.
77a12095d2SJakob Stoklund Olesen if (Level == 0)
78a12095d2SJakob Stoklund Olesen return NodeRef();
79a12095d2SJakob Stoklund Olesen
80a12095d2SJakob Stoklund Olesen // Go up the tree until we can go right.
81a12095d2SJakob Stoklund Olesen unsigned l = Level - 1;
82e7ed7b6cSJakob Stoklund Olesen while (l && atLastEntry(l))
83a12095d2SJakob Stoklund Olesen --l;
84a12095d2SJakob Stoklund Olesen
85a12095d2SJakob Stoklund Olesen // We can't go right.
86e7ed7b6cSJakob Stoklund Olesen if (atLastEntry(l))
87a12095d2SJakob Stoklund Olesen return NodeRef();
88a12095d2SJakob Stoklund Olesen
89a12095d2SJakob Stoklund Olesen // NR is the subtree containing our right sibling.
90a12095d2SJakob Stoklund Olesen NodeRef NR = path[l].subtree(path[l].offset + 1);
91a12095d2SJakob Stoklund Olesen
92a12095d2SJakob Stoklund Olesen // Keep left all the way down.
93a12095d2SJakob Stoklund Olesen for (++l; l != Level; ++l)
94a12095d2SJakob Stoklund Olesen NR = NR.subtree(0);
95a12095d2SJakob Stoklund Olesen return NR;
96a12095d2SJakob Stoklund Olesen }
97a12095d2SJakob Stoklund Olesen
moveRight(unsigned Level)98a12095d2SJakob Stoklund Olesen void Path::moveRight(unsigned Level) {
99a12095d2SJakob Stoklund Olesen assert(Level != 0 && "Cannot move the root node");
100a12095d2SJakob Stoklund Olesen
101a12095d2SJakob Stoklund Olesen // Go up the tree until we can go right.
102a12095d2SJakob Stoklund Olesen unsigned l = Level - 1;
103e7ed7b6cSJakob Stoklund Olesen while (l && atLastEntry(l))
104a12095d2SJakob Stoklund Olesen --l;
105a12095d2SJakob Stoklund Olesen
106a12095d2SJakob Stoklund Olesen // NR is the subtree containing our right sibling. If we hit end(), we have
107a12095d2SJakob Stoklund Olesen // offset(0) == node(0).size().
108a12095d2SJakob Stoklund Olesen if (++path[l].offset == path[l].size)
109a12095d2SJakob Stoklund Olesen return;
110a12095d2SJakob Stoklund Olesen NodeRef NR = subtree(l);
111a12095d2SJakob Stoklund Olesen
112a12095d2SJakob Stoklund Olesen for (++l; l != Level; ++l) {
113a12095d2SJakob Stoklund Olesen path[l] = Entry(NR, 0);
114a12095d2SJakob Stoklund Olesen NR = NR.subtree(0);
115a12095d2SJakob Stoklund Olesen }
116a12095d2SJakob Stoklund Olesen path[l] = Entry(NR, 0);
117a12095d2SJakob Stoklund Olesen }
118a12095d2SJakob Stoklund Olesen
119a12095d2SJakob Stoklund Olesen
distribute(unsigned Nodes,unsigned Elements,unsigned Capacity,const unsigned * CurSize,unsigned NewSize[],unsigned Position,bool Grow)120345945e3SJakob Stoklund Olesen IdxPair distribute(unsigned Nodes, unsigned Elements, unsigned Capacity,
121345945e3SJakob Stoklund Olesen const unsigned *CurSize, unsigned NewSize[],
122345945e3SJakob Stoklund Olesen unsigned Position, bool Grow) {
123345945e3SJakob Stoklund Olesen assert(Elements + Grow <= Nodes * Capacity && "Not enough room for elements");
124345945e3SJakob Stoklund Olesen assert(Position <= Elements && "Invalid position");
125345945e3SJakob Stoklund Olesen if (!Nodes)
126345945e3SJakob Stoklund Olesen return IdxPair();
127345945e3SJakob Stoklund Olesen
128345945e3SJakob Stoklund Olesen // Trivial algorithm: left-leaning even distribution.
129345945e3SJakob Stoklund Olesen const unsigned PerNode = (Elements + Grow) / Nodes;
130345945e3SJakob Stoklund Olesen const unsigned Extra = (Elements + Grow) % Nodes;
131345945e3SJakob Stoklund Olesen IdxPair PosPair = IdxPair(Nodes, 0);
132345945e3SJakob Stoklund Olesen unsigned Sum = 0;
133345945e3SJakob Stoklund Olesen for (unsigned n = 0; n != Nodes; ++n) {
134345945e3SJakob Stoklund Olesen Sum += NewSize[n] = PerNode + (n < Extra);
135345945e3SJakob Stoklund Olesen if (PosPair.first == Nodes && Sum > Position)
136345945e3SJakob Stoklund Olesen PosPair = IdxPair(n, Position - (Sum - NewSize[n]));
137345945e3SJakob Stoklund Olesen }
138345945e3SJakob Stoklund Olesen assert(Sum == Elements + Grow && "Bad distribution sum");
139345945e3SJakob Stoklund Olesen
140345945e3SJakob Stoklund Olesen // Subtract the Grow element that was added.
141345945e3SJakob Stoklund Olesen if (Grow) {
142345945e3SJakob Stoklund Olesen assert(PosPair.first < Nodes && "Bad algebra");
143345945e3SJakob Stoklund Olesen assert(NewSize[PosPair.first] && "Too few elements to need Grow");
144345945e3SJakob Stoklund Olesen --NewSize[PosPair.first];
145345945e3SJakob Stoklund Olesen }
146345945e3SJakob Stoklund Olesen
147345945e3SJakob Stoklund Olesen #ifndef NDEBUG
148345945e3SJakob Stoklund Olesen Sum = 0;
149345945e3SJakob Stoklund Olesen for (unsigned n = 0; n != Nodes; ++n) {
150345945e3SJakob Stoklund Olesen assert(NewSize[n] <= Capacity && "Overallocated node");
151345945e3SJakob Stoklund Olesen Sum += NewSize[n];
152345945e3SJakob Stoklund Olesen }
153345945e3SJakob Stoklund Olesen assert(Sum == Elements && "Bad distribution sum");
154345945e3SJakob Stoklund Olesen #endif
155345945e3SJakob Stoklund Olesen
156345945e3SJakob Stoklund Olesen return PosPair;
157345945e3SJakob Stoklund Olesen }
158345945e3SJakob Stoklund Olesen
159345945e3SJakob Stoklund Olesen } // namespace IntervalMapImpl
160345945e3SJakob Stoklund Olesen } // namespace llvm
161345945e3SJakob Stoklund Olesen
162