LLVM API Documentation

IntervalMap.cpp
Go to the documentation of this file.
00001 //===- lib/Support/IntervalMap.cpp - A sorted interval map ----------------===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This file implements the few non-templated functions in IntervalMap.
00011 //
00012 //===----------------------------------------------------------------------===//
00013 
00014 #include "llvm/ADT/IntervalMap.h"
00015 
00016 namespace llvm {
00017 namespace IntervalMapImpl {
00018 
00019 void Path::replaceRoot(void *Root, unsigned Size, IdxPair Offsets) {
00020   assert(!path.empty() && "Can't replace missing root");
00021   path.front() = Entry(Root, Size, Offsets.first);
00022   path.insert(path.begin() + 1, Entry(subtree(0), Offsets.second));
00023 }
00024 
00025 NodeRef Path::getLeftSibling(unsigned Level) const {
00026   // The root has no siblings.
00027   if (Level == 0)
00028     return NodeRef();
00029 
00030   // Go up the tree until we can go left.
00031   unsigned l = Level - 1;
00032   while (l && path[l].offset == 0)
00033     --l;
00034 
00035   // We can't go left.
00036   if (path[l].offset == 0)
00037     return NodeRef();
00038 
00039   // NR is the subtree containing our left sibling.
00040   NodeRef NR = path[l].subtree(path[l].offset - 1);
00041 
00042   // Keep right all the way down.
00043   for (++l; l != Level; ++l)
00044     NR = NR.subtree(NR.size() - 1);
00045   return NR;
00046 }
00047 
00048 void Path::moveLeft(unsigned Level) {
00049   assert(Level != 0 && "Cannot move the root node");
00050 
00051   // Go up the tree until we can go left.
00052   unsigned l = 0;
00053   if (valid()) {
00054     l = Level - 1;
00055     while (path[l].offset == 0) {
00056       assert(l != 0 && "Cannot move beyond begin()");
00057       --l;
00058     }
00059   } else if (height() < Level)
00060     // end() may have created a height=0 path.
00061     path.resize(Level + 1, Entry(nullptr, 0, 0));
00062 
00063   // NR is the subtree containing our left sibling.
00064   --path[l].offset;
00065   NodeRef NR = subtree(l);
00066 
00067   // Get the rightmost node in the subtree.
00068   for (++l; l != Level; ++l) {
00069     path[l] = Entry(NR, NR.size() - 1);
00070     NR = NR.subtree(NR.size() - 1);
00071   }
00072   path[l] = Entry(NR, NR.size() - 1);
00073 }
00074 
00075 NodeRef Path::getRightSibling(unsigned Level) const {
00076   // The root has no siblings.
00077   if (Level == 0)
00078     return NodeRef();
00079 
00080   // Go up the tree until we can go right.
00081   unsigned l = Level - 1;
00082   while (l && atLastEntry(l))
00083     --l;
00084 
00085   // We can't go right.
00086   if (atLastEntry(l))
00087     return NodeRef();
00088 
00089   // NR is the subtree containing our right sibling.
00090   NodeRef NR = path[l].subtree(path[l].offset + 1);
00091 
00092   // Keep left all the way down.
00093   for (++l; l != Level; ++l)
00094     NR = NR.subtree(0);
00095   return NR;
00096 }
00097 
00098 void Path::moveRight(unsigned Level) {
00099   assert(Level != 0 && "Cannot move the root node");
00100 
00101   // Go up the tree until we can go right.
00102   unsigned l = Level - 1;
00103   while (l && atLastEntry(l))
00104     --l;
00105 
00106   // NR is the subtree containing our right sibling. If we hit end(), we have
00107   // offset(0) == node(0).size().
00108   if (++path[l].offset == path[l].size)
00109     return;
00110   NodeRef NR = subtree(l);
00111 
00112   for (++l; l != Level; ++l) {
00113     path[l] = Entry(NR, 0);
00114     NR = NR.subtree(0);
00115   }
00116   path[l] = Entry(NR, 0);
00117 }
00118 
00119 
00120 IdxPair distribute(unsigned Nodes, unsigned Elements, unsigned Capacity,
00121                    const unsigned *CurSize, unsigned NewSize[],
00122                    unsigned Position, bool Grow) {
00123   assert(Elements + Grow <= Nodes * Capacity && "Not enough room for elements");
00124   assert(Position <= Elements && "Invalid position");
00125   if (!Nodes)
00126     return IdxPair();
00127 
00128   // Trivial algorithm: left-leaning even distribution.
00129   const unsigned PerNode = (Elements + Grow) / Nodes;
00130   const unsigned Extra = (Elements + Grow) % Nodes;
00131   IdxPair PosPair = IdxPair(Nodes, 0);
00132   unsigned Sum = 0;
00133   for (unsigned n = 0; n != Nodes; ++n) {
00134     Sum += NewSize[n] = PerNode + (n < Extra);
00135     if (PosPair.first == Nodes && Sum > Position)
00136       PosPair = IdxPair(n, Position - (Sum - NewSize[n]));
00137   }
00138   assert(Sum == Elements + Grow && "Bad distribution sum");
00139 
00140   // Subtract the Grow element that was added.
00141   if (Grow) {
00142     assert(PosPair.first < Nodes && "Bad algebra");
00143     assert(NewSize[PosPair.first] && "Too few elements to need Grow");
00144     --NewSize[PosPair.first];
00145   }
00146 
00147 #ifndef NDEBUG
00148   Sum = 0;
00149   for (unsigned n = 0; n != Nodes; ++n) {
00150     assert(NewSize[n] <= Capacity && "Overallocated node");
00151     Sum += NewSize[n];
00152   }
00153   assert(Sum == Elements && "Bad distribution sum");
00154 #endif
00155 
00156   return PosPair;
00157 }
00158 
00159 } // namespace IntervalMapImpl
00160 } // namespace llvm
00161