IntervalMap.cpp 4.4 KB

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