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