xref: /aosp_15_r20/external/llvm/lib/Support/IntervalMap.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
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