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